diegoveloper/flutter_keyboard_actions

Rebuild a keyboard when clicking on the input

Closed this issue · 9 comments

When i use the flutter_keyboard_actions lib, i have a problem which make me annoyed.
The keyboard always rebuilds when i click on the input (even when I have focused it before, i don't have this problem with a normal keyboard).
Do you have any solution for that ?

does it only happen when you use keyboard_actions ? can you try without using the package? if it's only with the package, add a minimum sample code to reproduce the issue.

I have this problem when i add this code before KeyboardActions:
GestureDetector( onPanDown: (_) => FocusScope.of(context).requestFocus(FocusNode()), child: KeyboardActions() )
Sorry for this inconvenience. This error is not coming from your library. I want to hide keyboard when user starts a scroll.

hmmm if you are using a focusNode object inside KeyboardActions , use the same object and call unfocus.

yourFocusNode.unfocus();

I have the same problem with your ideal.
GestureDetector( onPanDown: (_) => _firstNameFocus.unfocus(), child: KeyboardActions() );
When i put a GestureDetector inside KeyboardActions, it doesn't work (not hide keyboard when scrolling).
Otherwise, let GestureDetector outside of KeyboardActions, i have a rebuild of keyboard when i click on input (Definitely i have focused it).

Do you have any ideals for hiding a keyboard when scrolling ?

Yes, see my codes:

`import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:we_help/ui/common_widgets/common_widgets.dart';

class InscriptionContainer extends StatefulWidget {
const InscriptionContainer({this.transformY = 0, Key key}) : super(key: key);
final double transformY;

@OverRide
_InscriptionContainerState createState() => _InscriptionContainerState();
}

class _InscriptionContainerState extends State {
final TextEditingController _firstName = TextEditingController();
final FocusNode _firstNameFocus = FocusNode();
final GlobalKey _formInscriptionKey = GlobalKey();

@OverRide
void didUpdateWidget (InscriptionContainer oldWidget) {
super.didUpdateWidget(oldWidget);
if(oldWidget.transformY != widget.transformY) {
_initParams();
}
}

@OverRide
Widget build(BuildContext context) {
return Form(
key: formInscriptionKey,
child: GestureDetector(
onPanDown: (
) => _firstNameFocus.unfocus(),
child: KeyboardActions(
config: _buildKeyboardConfig(context),
child: Container(
height: MediaQuery.of(context).size.height - widget.transformY,
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 20),
child: SingleChildScrollView(
child: Column(
children: [
TextField(
controller: _firstName,
focusNode: _firstNameFocus,
),
],
),
),
),
),
),
);
}

KeyboardActionsConfig _buildKeyboardConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Theme.of(context).scaffoldBackgroundColor,
nextFocus: false,
actions: [
_buildKeyboardNextItem(_firstNameFocus),
]
);
}

KeyboardActionsItem _buildKeyboardNextItem(FocusNode focusNode) {
return KeyboardActionsItem(
focusNode: focusNode,
toolbarButtons: <Widget Function(FocusNode)>[
(FocusNode focusNode) {
return ButtonKeyboard(
text: 'Next',
color: Theme.of(context).primaryColor,
onPressed: () => focusNode.unfocus(),
);
}
],
);
}

void _initParams() {
setState(() {
_firstName.text = '';
});
}

@OverRide
void dispose() {
super.dispose();
_firstName.dispose();
_firstNameFocus.dispose();
}
}`

Add a sample without code that I can't run here -> import 'package:we_help/ui/common_widgets/common_widgets.dart';

Reduce the sample.

Okk, see my sample. Thank you ! 👍

`import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:keyboard_actions/keyboard_actions.dart';

class InscriptionContainer extends StatefulWidget {
const InscriptionContainer({Key key}) : super(key: key);

@OverRide
_InscriptionContainerState createState() => _InscriptionContainerState();
}

class _InscriptionContainerState extends State {
final TextEditingController _firstName = TextEditingController();
final FocusNode _firstNameFocus = FocusNode();
final GlobalKey _formInscriptionKey = GlobalKey();

@OverRide
Widget build(BuildContext context) {
return Form(
key: formInscriptionKey,
child: GestureDetector(
onPanDown: (
) => _firstNameFocus.unfocus(),
child: KeyboardActions(
config: _buildKeyboardConfig(context),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 20),
child: SingleChildScrollView(
child: Column(
children: [
TextField(
controller: _firstName,
focusNode: _firstNameFocus,
),
],
),
),
),
),
),
);
}

KeyboardActionsConfig _buildKeyboardConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Theme.of(context).scaffoldBackgroundColor,
nextFocus: false,
actions: [
_buildKeyboardNextItem(_firstNameFocus),
]);
}

KeyboardActionsItem _buildKeyboardNextItem(FocusNode focusNode) {
return KeyboardActionsItem(
focusNode: focusNode,
toolbarButtons: <Widget Function(FocusNode)>[
(FocusNode focusNode) {
return GestureDetector(
onTap: () => focusNode.unfocus(),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.close),
),
);
}
],
);
}

void _initParams() {
setState(() {
_firstName.text = '';
});
}

@OverRide
void dispose() {
super.dispose();
_firstName.dispose();
_firstNameFocus.dispose();
}
}
`

Try this solution:

class _InscriptionContainerState extends State {
  final TextEditingController _firstName = TextEditingController();
  final FocusNode _firstNameFocus = FocusNode();
  final GlobalKey _formInscriptionKey = GlobalKey();
  bool _focused = false;

  Future<void> _listenFocus() async {
    await Future.delayed(const Duration(milliseconds: 1000));
    _focused = FocusScope.of(context).isFirstFocus;
  }

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) => FocusScope.of(context).addListener(_listenFocus));
    super.initState();
  }

  @override
  void deactivate() {
    FocusScope.of(context).removeListener(_listenFocus);
    super.deactivate();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formInscriptionKey,
      child: NotificationListener<ScrollNotification>(
        onNotification: (details) {
          if (_focused) {
            FocusScope.of(context).unfocus();
          }
          return true;
        },
        child: KeyboardActions(
          config: _buildKeyboardConfig(context),
          child: Padding(
            padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 20),
            child: SingleChildScrollView(
              child: Column(
                children: List.generate(
                    30,
                    (index) => Padding(
                          padding: const EdgeInsets.all(30),
                          child: TextField(),
                        )),
              ),
            ),
          ),
        ),
      ),
    );
  }