6

I need to focus on a TextField but without showing the keyboard. The keyboard needs to be shown only if the user taps on the TextField.

I tried 2 ways.

First attempt:

This way the keyboard shows and it's hidden after screen build which is not nice to see.

Builder:

TextFormField(
    controller: barcodeStringController,
    focusNode: myFocusNode,
    autofocus: true,
    textAlign: TextAlign.right,
    textInputAction: TextInputAction.done,
    textCapitalization: TextCapitalization.characters,
    style: TextStyle(fontSize: 20),
    maxLines: null,
    onTap: () {
      SystemChannels.textInput.invokeMethod('TextInput.show');
    },
    //... Other event listeners to handle submit
),

And out of build():

void _onAfterBuild(BuildContext context) {
  SystemChannels.textInput.invokeMethod('TextInput.hide');
}

Second attempt:

This way the keyboard is hidden at a lower level and it's nicer to see. The problem is that onTap is never called so the keyboard never shows, neither onTap.

Builder:

GestureDetector(
    onTap: () {
        SystemChannels.textInput.invokeMethod('TextInput.show');
    },
    child: TapOnlyFocusTextField(
        controller: barcodeStringController,
        focusNode: myFocusNode, //this is a TapOnlyFocusTextFieldFocusNode
        textAlign: TextAlign.right,
        textInputAction: TextInputAction.done,
        textCapitalization: TextCapitalization.characters,
        style: TextStyle(fontSize: 20),
        cursorColor: Colors.black,
        //... Other event listeners to handle submit
    ),
),

TapOnlyFocusTextField Class:

class TapOnlyFocusTextField extends EditableText {
  TapOnlyFocusTextField({
    @required TextEditingController controller,
    @required TextStyle style,
    @required Color cursorColor,
    bool autofocus = false,
    Color selectionColor,
    FocusNode focusNode,
    TextAlign textAlign,
    TextInputAction textInputAction,
    TextCapitalization textCapitalization,
    onSubmitted,
    onChanged,
  }) : super(
          controller: controller,
          focusNode: focusNode,
          style: style,
          cursorColor: cursorColor,
          autofocus: autofocus,
          selectionColor: selectionColor,
          textAlign: textAlign,
          textInputAction: textInputAction,
          textCapitalization: textCapitalization,
          maxLines: null,
          onSubmitted: onSubmitted,
          backgroundCursorColor: Colors.black,
          onChanged: onChanged,
        );

  @override
  EditableTextState createState() {
    return TapOnlyFocusTextFieldState();
  }
}

class TapOnlyFocusTextFieldState extends EditableTextState {
  @override
  void requestKeyboard() {
    super.requestKeyboard();
    //hide keyboard
    SystemChannels.textInput.invokeMethod('TextInput.hide');
  }
}

TapOnlyFocusTextFieldFocusNode Class:

class TapOnlyFocusTextFieldFocusNode extends FocusNode {
  @override
  bool consumeKeyboardToken() {
    // prevents keyboard from showing on first focus
    return false;
  }
}

I know that there's already an open issue in Flutter Github about this but I need to find a solution: https://github.com/flutter/flutter/issues/16863

creativecreatorormaybenot
  • 91,704
  • 51
  • 240
  • 358
Davide Bicego
  • 480
  • 1
  • 5
  • 20
  • Are you sure the `GestureDetector` `onTap` is never called (have you added a print statement e.g.)? Tap events are passed down the tree, so the `GestureDetector` should consume it first. I might know a solution, but I am confused by this. Also, have you tested other `GestureDetector` callbacks? It might not be your desired behavior, but it can show useful insights if e.g. a long press on the text field triggers the gesture detector long press. – creativecreatorormaybenot Nov 27 '19 at 15:55
  • @creativecreatorormaybenot Yeah, neither onTap or onLongPress are being called – Davide Bicego Nov 27 '19 at 16:05
  • The problem in the second attempt is GestureDetector onTap not being called. I tried creating a button to show the keyboard and it works ok. – Davide Bicego Nov 27 '19 at 16:13
  • 1
    After further investigation I found out that onTap is called but not all the times (this is really strange) and I don't found out why. – Davide Bicego Nov 27 '19 at 16:51
  • Did you ever find a proper solution to your problem here? – Christo Carstens Jul 19 '21 at 01:27

2 Answers2

0

The text_input.dart has a method

    void show({bool ifShowKeyBoard = true}) {
      assert(attached);
      if (ifShowKeyBoard) {
        TextInput._instance._show();
      }
    }

I changed the method as this,It works

YuHao Zhu
  • 44
  • 3
0

As it is shown here: https://stackoverflow.com/a/60392327/4693979

But I prefer do this in initState:

  void initState() {
    super.initState();
    Future.delayed(
      Duration(),
      () => SystemChannels.textInput.invokeMethod('TextInput.hide'),
    );
  }

Do not forget to set autofocus to true.

K.Amanov
  • 855
  • 11
  • 19