43

In my case i need to scan barcode and fetch product details. Normally barcode scanner devices emit enter key(keycode=13) event at end of scanning, But in flutter enter key is not same as Done so how can code to detect enter key pressed in my TextFormField widget?

Benjith Kizhisseri
  • 2,311
  • 2
  • 13
  • 24

5 Answers5

56

if you are using TextField then you have to add onSubmitted in your text field to detect when user press Enter key. For my case, I changed Done in keyboard to TextInputAction.Search. It also works for TextInputAction.Done too. here is a sample code

   TextField(
    onSubmitted: (value){
      //value is entered text after ENTER press
      //you can also call any function here or make setState() to assign value to other variable
    },
    textInputAction: TextInputAction.search,
  )
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
Al Walid Ashik
  • 1,545
  • 20
  • 32
  • When I try to use this (On Flutter Web), and I tap the enter key on my physical keyboard, the only thing that happens is the TextField loses focus. Any ideas why this may not work? – Shawn Ashton Jul 19 '22 at 23:32
  • @ShawnAshton I'm sorry that I couldn't help you on this as I never tried flutter web yet! – Al Walid Ashik Jul 20 '22 at 01:32
20

The solution above works, but I believe RawKeyboardListener is a more reliable and flexible solution. You just need to cover the text field with it and start to listen to keyboard events:

var focusNode = FocusNode();
RawKeyboardListener(
        focusNode: focusNode,
        onKey: (event) {
          if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
            // Do something
          }
        },
        child: TextField(controller: TextEditingController())
    )

As a second option you can use onKey method of the FocusNoded and pass the node to your text field:

var focusNode = FocusNode(onKey: (node, event) {
    if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
        // Do something
        // Next 2 line needed If you don't want to update the text field with new line.
        // node.unfocus(); 
        // return true;
    }
    return false;

});
TextField(focusNode: focusNode, controller: TextEditingController())
  • The first solution looks good to me but how does it trigger 'onSubmitted' of the TextField when the enter key is pressed? – Rivers Cuomo May 17 '21 at 12:30
  • Update: I see. I moved the function from the 'onSubmitted' of the TextField to 'Do something' block in your suggestion. And I supplied it with the text from the TextEditingController in the TextField. Works great. – Rivers Cuomo May 17 '21 at 12:45
  • 2
    ...but only for physical keyboards. – Rivers Cuomo May 17 '21 at 15:33
  • 2
    Since `onKey` will be deprecated soon, is there an equivalent way of doing this with `onKeyEvent`? It doesn't seem to recognize `enter`. – sleighty Oct 14 '21 at 01:34
  • 1
    I agree to @RiversCuomo, I am debugging using laptop, and it could not listen to keyboard enter key, other keys are logged except it. – josevoid May 24 '22 at 08:15
  • I get `The return type 'bool' isn't a 'KeyEventResult', as required by the closure's context.` for the `onKey` handler. – Luke Hutchison Mar 11 '23 at 03:17
12

In case someone is looking for the same solution (as Al Walid Ashik) but for TextFormField, just use the following:

TextFormField(
  /// ...
  onFieldSubmitted: (value) {
     /// do some stuff here
  },
),
loonix
  • 430
  • 7
  • 14
  • Is there a way to prevent the form field losing focus when implementing this? – sleighty Oct 14 '21 at 01:35
  • 1
    That sounds like another question, https://stackoverflow.com/questions/63492002/flutter-how-to-keep-textfield-focus-on-submit – loonix Oct 14 '21 at 07:37
6
TextFormField(
maxLines: null,
autovalidate: true,
   validator: (value){
             if(value.contains('\n')){
              doFun(value);
              }   
            }

)

When user press enter key new line create in text box. We check with that.

maxLine:null - to hide multiline

autovalidate:true -to automatically run validator fun

'\n' - new line ('\s'-whitespace,'\t'-tab.. etc)

Benjith Kizhisseri
  • 2,311
  • 2
  • 13
  • 24
  • 1
    This solution almost works for me - the problem is that with maxLines = null, the text field grows when you hit Enter. Any way to make it stay one line tall (without losing the '\n')? – Lars335 Nov 09 '19 at 01:02
  • @Lars335 were u able to solve it in case maxLines=null – Harshvardhan R Jan 12 '21 at 18:05
4

In addition to the Sergey Yamshchikov's answer:

In case if it is a multiline TextField (maxLines: null) and you want to catch up the entered key and prevent passing it into the text field, you can use this approach:

RawKeyboardListener(
    focusNode: FocusNode(onKey: (node, event) {
              if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
                return KeyEventResult.handled; // prevent passing the event into the TextField
              }
              return KeyEventResult.ignored; // pass the event to the TextField
            }),
    onKey: (event) {
      if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
        // Do something
      }
    },
    child: TextField(controller: TextEditingController())
)

But, if you need to detect the keys combination, like ctrl+enter, then you can use CallbackShortcuts:

CallbackShortcuts(
  bindings: {
    const SingleActivator(LogicalKeyboardKey.enter, control: true): _doSomething(),
  },
  child: Focus(
    autofocus: true,
    child:  TextField(controller: TextEditingController()),
  ),
);
user2134488
  • 451
  • 5
  • 13
  • 1
    This helped me as it lets you have a multi line textField and stop it adding a new line when you press enter! – Mijawel Jun 14 '22 at 02:04