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

3

10

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?

Tincher answered 28/9, 2020 at 18:47 Comment(0)
T
22

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.

Tincher answered 28/9, 2020 at 19:54 Comment(2)
unfocus works for me, but the GestureDetector will only catch it if nothing else catches the tap. So any other buttons on the screen have to also call unfocus.Fic
@Fic Did you solve the issue mentioned in the comment above?Hypocotyl
R
10

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');
   }
Retinite answered 28/9, 2020 at 18:54 Comment(2)
I'd already tried FocusScope.of(context).requestFocus(FocusNode());, it still has the same problem where the focus comes back after I open the time picker. The SystemChannels method didn't fix it either, it just hides the keyboard without removing focus, and then the keyboard comes back when I open the time picker.Tincher
SystemChannels.textInput.invokeMethod('TextInput.hide'); this one workig for google place autocomplete ThanksMachiavellian
W
2

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.

Wyler answered 4/1, 2022 at 11:19 Comment(1)
FocusNode must be created as a state variable and must be properly disposed.Carrew

© 2022 - 2024 — McMap. All rights reserved.