How to hide the keyboard on scroll in Flutter
I've recently had to hide the keyboard on scroll in my app. Once the user has finished typing, they typically scroll down. By hiding the keyboard, they gain a lot of real estate.
First try: ScrollController
My view uses a SingleChildScrollView
to show scrollable content. My first try was to introduce a ScrollController
and listen to it:
ScrollController scrollController;
@override
void initState() {
scrollController = ScrollController();
scrollController.addListener(hideKeyboard);
super.initState();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
controller: scrollController,
child: Column(...)
);
}
hideKeyboard() {
FocusScope.of(context).requestFocus(FocusNode());
}
And it worked great!... Most of the time.
There are times where it will hide the keyboard even though I am not actively scrolling. For example if I select a slightly hidden TextField, the keyboard will briefly appear, and then disappear as the TextField scrolls into view.
Second try: GestureDetector
@override
Widget build(BuildContext context) {
return GestureDetector(
onVerticalDragDown: (_) {
hideKeyboard();
},
child: SingleChildScrollView(...));
}
I've been wondering if I should change the behavior
of the GestureDetector
. The doc says it defaults to HitTestBehavior.deferToChild
, which means that the GestureDetector
will handle the event if the touch event hits one of its children. That's what we want. So we can keep the default.
Also, I initially used onVerticalDragStart
. The doc says it'll trigger when "[it] has begun to move vertically." but it didn't work. I had to use onVerticalDragDown
. My guess is that the scroll is done its child, the SingleChildScrollView
, not by the GestureDetector
itself, so the vertical drag will technically never "start".