How to detect when a TextField is selected in Flutter?

KeyboardTextfieldFlutter

Keyboard Problem Overview


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.

Keyboard Solutions


Solution 1 - Keyboard

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 - Keyboard

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 - Keyboard

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

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

Solution 4 - Keyboard

Simply use onTap function of TextField.

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

Solution 5 - Keyboard

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,
  ),
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2785693View Question on Stackoverflow
Solution 1 - KeyboardHemanth RajView Answer on Stackoverflow
Solution 2 - KeyboardavikamView Answer on Stackoverflow
Solution 3 - KeyboardAnkur PrakashView Answer on Stackoverflow
Solution 4 - KeyboardsanjayView Answer on Stackoverflow
Solution 5 - KeyboardAl Walid AshikView Answer on Stackoverflow