'TextField is gaining focus after navigating to another screen
In my project I've wrapped the whole MaterialApp
in a GestureDetector
which is supposed to dismiss keyboard when user tapped the screen, using this piece of code
FocusScope.of(context).unfocus()
After testing multiple scenarios it wasn't working so I decided to do it the wrong way
FocusScope.of(context).requestFocus(FocusNode())
But now I'm experiencing another issue. Here is my code for a simple screen which is instantiated by MaterialApp
's routes
builder.
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
@override
_TestScreenState createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
TextFormField(),
FlatButton(
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => TestScreen())),
child: Text('Test'))
],
),
);
}
}
The steps to reproduce error is: 1-Start editing TextField
. 2-Unfocus TextField
by tapping somewhere on screen. 3-Tap on button to navigate to another screen. This is the result:
This behavior is not happening when I'm trying to unfocus TextField
by pressing keyboard's done button. According to the source code when done button is pressed, TextField
is calling clearComposing
on TextEditingController
. I even tried that but got no luck. How can I fix it? Does anyone else have better solution to handle dismissing keyboard in Flutter?
Also here is my flutter doctor
result:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.17.5, on Mac OS X 10.15.5 19F101, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 11.6)
[✓] Android Studio (version 4.0)
[✓] VS Code (version 1.47.3)
[✓] Connected device (2 available)
• No issues found!
Solution 1:[1]
After searching a lot on GitHub issues related to focus management, It seems that no one knows what is the right way to do this. Finally this line of code solved my issue:
WidgetsBinding.instance.focusManager.primaryFocus?.unfocus();
I'm not aware of side effects of it but It's working for now.
Solution 2:[2]
You are facing two problems here:
The expected behaviour in flutter is when pushing to a new route the focus of the previous route persists, which implies that when you pop back the
TextField
is still on focus. Refer to this flutter github discussion about the topic.You have two
GestureDetector
's which are tringgered by an onTap pointer gesture. Your wrapper which you use to dismiss the focus, and theFlatButton
to navigate to the other route. When you tap the button the underlyingGestureRecognizer
gives the hanlding control of this event to the button, and the wrapperGestureDetector
opTap() is not called (which implies unfocus is not called).
Solution 3:[3]
Set a focusNode to the text field and, after push the new route, focus next node and unfocus current, like:
// push your new route here
myNode.nextFocus();
myNode.unfocus();
// myNode needs to be the last text field
When you press back, from the new route, the focus will not reappear automatically anymore.
Worked for me.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | pcba-dev |
Solution 3 | Márcio Valim |