How to fully unfocus TextField in flutter without focus coming back later

Viewed 6774

In my flutter app, I have a textfield that I want to be able to remove focus from by tapping a non-interactable component. This is not the default behaviour of textfields in flutter, so I need to find a way to manually do it. I've got it somewhat working by following the steps at https://flutterigniter.com/dismiss-keyboard-form-lose-focus/ and various other pages, which involves a GestureDetector at the root with an onTap that looks something like this:

onTap: () {
  FocusScopeNode cf = FocusScope.of(context);
  if (!cf.hasPrimaryFocus && cf.focusedChild != null) {
    cf.focusedChild.unfocus();
    cf.unfocus();
  }
}

The problem is that when I select the text field, click somewhere else (focus appears to disappear at this point), open a time picker, and close that time picker, the textfield is focused again. If I unfocus the textfield by clicking the "done" button on the keyboard instead, then opening/closing a time picker won't refocus the textfield, so I know it has to be a problem with the way I'm unfocusing it. What's the correct way of unfocusing it so focus won't come back like that?

3 Answers

I figured it out, it looks like I needed to use onTap: () => FocusManager.instance.primaryFocus.unfocus() in the GestureDetector at the root. I'm pretty sure that's the best solution to this particular problem, though I'm not sure if it can cause side effects.

wrap your whole screen to GestureDetector there are two ways to dismiss the keyboard\

  1. FocusScope.of(context).requestFocus(FocusNode());
import 'package:flutter/services.dart';

SystemChannels.textInput.invokeMethod('TextInput.hide');

so please try you code with this

import 'package:flutter/services.dart';
onTap(){
    SystemChannels.textInput.invokeMethod('TextInput.hide');
   }

What worked for me without the need to call the unfocus method is that I tell TextField itself not to request focus on its own. In the text field itself I added:

focusNode: FocusNode(canRequestFocus: false),

I believe this is the correct way to handle that.

Related