Detect a tap outside of a TextField to unfocus - flutter

I want to hide the keyboard when the user taps outside of a TextField. My current solution is to listen to taps in a GestureDetector that wraps the screen and call FocusScope.of(context).unfocus() to hide the keyboard.
The problem is that the GestureDetector doesn't detect taps on widgets like buttons. So when a button is tapped, the keyboard doesn't hide.

Since Button widgets handles their own gesture, you can just add FocusScope.of(context).unfocus() on your buttons' onPressed()
ElevatedButton(
onPressed: () {
// Unfocus from any focused TextField
FocusScope.of(context).unfocus();
// Do button function
},
child: Text('...'),
)

Related

Swipe back in flutter. without any button

How Can I swipe for back in Flutter? not tap back button.
Without any button......
Just swipe from left to right. And go to the back page
you can wrap your screen widget with gesture detector and on detecting swipe left you can pop the screen like this
GestureDetector(
onPanUpdate: (details) {
if (details.delta.dx > 0) {
Navigator.of(context).pop();
}
},
child: Scaffold(
body: ///your body
),
);
Edit:
The above solution was the one that came to my mind and i got another answer on stack-overflow maybe that one is the correct way to do it here is the answer
https://stackoverflow.com/a/55577584/14466860

How to make able to scroll ListView inside SingleChildScrollView?

How to make able to scroll listview inside SingleChildScrollView?
That's right, normally the list view scrolls even if the parent is a SingleChildScrollView.
But my case is special because I used
NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification is UserScrollNotification) {
if (notification.direction == ScrollDirection.forward) {
//trigger doing some event ...
...changing screen because of this event
So my Listview scrolling is absolutely doing nothing and changing the screen because of the parent event.
child: ListView.builder( ... // when scroll it doesn`t scroll and change screen because of parent
Can anyone solve this?
I think you have not provided the physics property for the list view:
Use -> physics:AlwaysScrollableScrollPhysics() for the listview to make it scrollable.

Dismiss the keyboard after all fields in a form are filled in Flutter?

I am making a sign-up form. My problem is when the user fills the last field in my form and hit enter on the keyboard, but the keyboard does not dismiss. Is there any way to dismiss the keyboard?
If you want to dismiss the keyboard when the user clicks anywhere on the screen:
wrap the scaffold with GestureDetector:
GestureDetector(
onTap: () {
setState(() {
FocusScope.of(context).requestFocus(new FocusNode());
});
},
child: Scaffold());
If you want to dismiss the keyboard when the user fills the last textField:
track the textfields controllers and when you are at the last one use yourControllerName.unfocus();

Dismiss keyboard on swipe back gesture in Flutter app

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.
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()],
)
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.
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...
},
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();
}

How to not dismiss the keyboard when the showMenu method invoke in flutter?

I have ComposePage have a TextField and action button, when press the button show menu,but I not hope to dismiss the keyboard,In flutter how to do this!
add this code in onPress function.
FocusScope.of(context).requestFocus(new FocusNode());