Reputation: 909
I am trying to dismiss the keyboard when the user swipes from the edge to pop route.
Currently the keyboard doesn't dismiss until the route is completely gone popped, messing up some of the other pages layout until it dismisses
I did try to use a WillPopScope
to determine when the user was going to pop the route, but unfortunately this disables the swipe to pop functionality from iOS or the CupertinoPageRoute
.
I just want to find out if there's anyway I can determine when the user swipes from the edge to pop or taps the back button on the appBar and dismiss the keyboard as they do so.
If possible, I am trying to dismiss keyboard as soon as they start swiping to pop, as it happens in many apps.
I am attaching attaching a gif showing the effect I'm trying to achieve.
Upvotes: 7
Views: 3913
Reputation: 354
this is something i wrote to handle this issue. doesnt use any external packages, you would just wrap your content in the main function at the top.
Widget swipeOffKeyboard(BuildContext context, {Widget? child}) {
return Listener(
onPointerMove: (PointerMoveEvent pointer) {
disKeyboard(pointer, context);
},
child: child, // your content should go here
);
}
void disKeyboard(PointerMoveEvent pointer, BuildContext context) {
double insets = MediaQuery.of(context).viewInsets.bottom;
double screenHeight = MediaQuery.of(context).size.height;
double position = pointer.position.dy;
double keyboardHeight = screenHeight - insets;
if (position > keyboardHeight && insets > 0) FocusManager.instance.primaryFocus?.unfocus();
}
Upvotes: 0
Reputation: 909
As suggested by Ovidiu
class DismissKeyboardNavigationObserver extends NavigatorObserver {
@override
void didStartUserGesture(Route route, Route previousRoute) {
SystemChannels.textInput.invokeMethod('TextInput.hide');
super.didStartUserGesture(route, previousRoute);
}
}
and in your Material App
MaterialApp(
navigatorObservers: [DismissKeyboardNavigationObserver()],
)
Upvotes: 3
Reputation: 8714
You need to create a custom class extending NavigatorObserver
, and pass an instance of it to the navigatorObservers
property of your MaterialApp
or CupertinoApp
.
Within that custom class, you can override didStartUserGesture
and didStopUserGesture
, which will be called when the swipe gesture starts/ends. This should allow you to achieve the behavior you are looking for. Note that didStartUserGesture
indicates the current route as well as the previous route, based on which you could add logic to determine whether the keyboard should be dismissed or not.
Upvotes: 2
Reputation: 17756
This should come naturally and you shouldn't be directly concerned with that because actually, when you pop a route with the keyboard on, it should dismiss properly.
However, if you want to detect when the user starts swiping and dismiss the keyboard along with it and then pop the current route, you can easily achieve it by wrapping your screen widget with a GestureDetector
like so:
Widget build(BuildContext context) {
double dragStart = 0.0;
return GestureDetector(
onHorizontalDragStart: (details) => dragStart = details.globalPosition.dx,
onHorizontalDragUpdate: (details) {
final double screenWidth = MediaQuery.of(context).size.width;
// Here I considered a back swipe only when the user swipes until half of the screen width, but you can tweak it to your needs.
if (dragStart <= screenWidth * 0.05 && details.globalPosition.dx >= screenWidth) {
FocusScope.of(context).unfocus();
}
child: // Your other widgets...
},
Upvotes: 0