How to detect when a TextField is selected in Flutter?

61,058

Solution 1

I suppose you are looking for FocusNode.

To listen to focus change, you can add a listner to the FocusNode and specify the focusNode to TextField.

Example:

class TextFieldFocus extends StatefulWidget {
  @override
  _TextFieldFocusState createState() => _TextFieldFocusState();
}

class _TextFieldFocusState extends State<TextFieldFocus> {
  FocusNode _focus = FocusNode();

  TextEditingController _controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    _focus.addListener(_onFocusChange);
  }

  @override
  void dispose() {
    super.dispose();
    _focus.removeListener(_onFocusChange);
    _focus.dispose();
  }

  void _onFocusChange() {
    debugPrint("Focus: ${_focus.hasFocus.toString()}");
  }
  
  @override
  Widget build(BuildContext context) {
    return new Container(
      color: Colors.white,
      child: new TextField(
        focusNode: _focus,
      ),
    );
  }
}

This gist represents how to ensure a focused node to be visible on the ui.

Hope it helps!

Solution 2

To be notified about a focus event, you can avoid manually managing widget's state, by using the utility classes FocusScope, Focus.

From the docs (https://api.flutter.dev/flutter/widgets/FocusNode-class.html):

Please see the Focus and FocusScope widgets, which are utility widgets that manage their own FocusNodes and FocusScopeNodes, respectively. If they aren't appropriate, FocusNodes can be managed directly.

Here is a simple example:

FocusScope(
  child: Focus(
    onFocusChange: (focus) => print("focus: $focus"),
    child: TextField(
      decoration: const InputDecoration(labelText: 'City'),
    )
  )
)

Solution 3

The easiest and simplest solution is to add the onTap method on TextField.

TextField(
  onTap: () {
    print('Editing stated $widget');
  },
)

Solution 4

Simply use onTap function of TextField.

TextField(
  onTap: () {
    // Your code.
  },
);

Solution 5

There is another way if your textfield needs to be disabled for some purpose like mine. for that case, you can wrap your textField with InkWell like this,

InkWell(
  onTap: () {
    print('clicked');
  },
  child: TextField(
    enabled: false,
  ),
);
Share:
61,058
user2785693
Author by

user2785693

Retired professionally but still tinker with code.

Updated on January 07, 2022

Comments

  • user2785693
    user2785693 over 2 years

    I have a Flutter TextField which gets covered by the soft keyboard when the field is selected. I need to scroll the field up and out of the way when the keyboard is displayed. This is a pretty common problem and a solution is presented in this StackOverflow post.

    I think I have the ScrollController part figured out but how do I detect when the TextField has been selected? There doesn't appear to be any event method (e.g. onFocus(), onSelected(), onTap(), etc).

    I tried wrapping the TextField in a GestureDetector but that didn't work either -- apparently the event was never captured.

    new GestureDetector(
      child: new TextField(
        decoration: const InputDecoration(labelText: 'City'),
      ),
      onTap: () => print('Text Selected'),
    ),
    

    This is such a basic requirement that I know there must be an easy solution.

  • user2785693
    user2785693 about 6 years
    Thank you so very much for this answer. I haven't attempted to utilize the more robust solution you offered in the gist but the simple solution below seems to work in my test case.
  • Qiong Wu
    Qiong Wu about 6 years
    I have an issue with this solution, since I am showing an overlay on focusing the textfield. showing the overlay works like a charm, but as soon as the overlay is closed, the textfield is autofocused again, and the overlay pops up again
  • Hemanth Raj
    Hemanth Raj about 6 years
    before showing the dialog just invoke unfocus method on the same focus node. Do it only if you did not wanted the textfield to be focused when you come back.
  • Günter Zöchbauer
    Günter Zöchbauer about 5 years
    There are other means for a TextField to get focus, for example if it's the first TextField on a page and future Flutter versions will support tabbing through fields.
  • Renan Coelho
    Renan Coelho over 4 years
    Saved me! Thank you!
  • Ryan R
    Ryan R about 4 years
    Simple and concise.
  • stpch
    stpch about 4 years
    The focus node should also be cleaned up in the stateful widget's dispose(). See the example on api.flutter.dev/flutter/widgets/FocusNode-class.html.
  • Hesam
    Hesam over 3 years
    don't forget to dispose it in dispose();
  • Eradicatore
    Eradicatore about 3 years
    Great answer, thanks. I do see though, if I advance the focus to the next text field with node.nextFocus() then I don't have access to the controller for the next field to set the selection like I do with your onTap() solution. hmmm
  • Iosif Pop
    Iosif Pop about 3 years
    Great answer. Thanks!
  • TGLEE
    TGLEE about 3 years
    For me, this answer worked better than the accepted answer because the callback gets called only when the child widget 'TextField' is tapped for entering text. With 'addListener' method from the accpepted answer, it was not the case. Some of parents widget would trigger the callback too when tapped. I didn't quite understand why..
  • Marwin Lebensky
    Marwin Lebensky almost 3 years
    On android, if you press the system backbutton while in a TextField then [onFocusChange] will not be triggered.
  • Harini Sampath
    Harini Sampath over 2 years
    _focus.removeListner, and _focus.dispose in the dispose()
  • Yogi Arif Widodo
    Yogi Arif Widodo over 2 years
    but when we trigger a popup the focuscope trigger against on focus, so my datepicker open against.