Removing keyboard focus on multiple buttons pressed - flutter

I'm trying to hide keyboard when tapped everywhere outside of textField. So I wrapped Scaffold with GestureDetector and set onTap with unfocused(). That works well however when a button is pressed then the keyboard is still active
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Scaffold(
appBar: AppBar(
actions: <Widget>[FlatButton(child: Text('Done'), onPressed: () {})],
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
FlatButton(
child: Text('something'),
onPressed: () {},
),
TextField(),
],
),
),
);
}
Is there any way to remove the focus without adding that unfocused in onTap of all buttons.. Reason is I've got many buttons there and some has even onLogTap set so there would be a lot of duplicate codes

You need to also add code for hide keyboard inside onPressed() method of FlatButton
FlatButton(
child: Text('something'),
onPressed: () {
FocusScope.of(context).unfocus();
},
),
was hoping for some solution where I wouldn't need so many duplicate codes to do one thing.
AFAIK that is not possible because the click event of GestureDetector widget and click event of FlatButton both are different,
You are registering different/separate click event of FlatButton that's why your keyboard is not hiding when you click on FlatButton
Now the reason why your keyboard not hiding when pressed on buttons
Because the click event of your GestureDetector widget if overridden by the click event of your FlatButton
SOLUTION
You can do one thing, create a common method to hide the keyboard, and call that method to from button click

By thinking a little outside of the box I have managed to hide keyboard on all taps by modifying GestureDetector..
Widget build(BuildContext context) {
return GestureDetector(
onPanDown: (pd) {FocusScope.of(context).unfocus();}, //<- replaced
child: Scaffold(
appBar: AppBar(
actions: <Widget>[FlatButton(child: Text('Done'), onPressed: () {})],
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
FlatButton(
child: Text('something'),
onPressed: () {},
),
TextField(),
],
),
),
);
}
Now the keyboard will hide on taping everywhere outside of the TextField even on Buttons click.. No need to hide it in each button click. Please if you know about better solution then let me know
UPDATE:
This solution will create exception when tap on already focused TextField

Related

Howto hide the keyboard in flutter when tapping outside of the TextField without triggering any other actions?

Hi I have the following (simplified) code:
class Example extends StatelessWidget {
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).focusedChild?.unfocus(),
child: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print("Button pressed!");
},
child: Text("Click me"),
),
TextField(),
],
),
),
);
}
}
This code results in the following UI:
When I click on the blue button, "Button pressed!" gets printed and the keyboard does not disappear.
The problem here, is that this behavior is not what I want. I want that the keyboard disappears when I click somewhere outside of the TextField, and that the button does not get triggered, even when I directly click on it. So for example if I click on the button just the keyboard should disappear without any other action/side effect (nothing gets printed in this case). But it should still be possible to interact with the TextField normally.
Note: Disabling the button is not a good option since in my real case scenario the page is build out of a lot complex widgets and disabling them is really complicated.
Already stuck there for a while now. Hope you can help me :)
Wrap the Scaffold with Gesture detector and on tap unfocus the focus scope
example
class Test extends StatelessWidget {
const Test({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: const Scaffold(),
);
}
}
Wrap your Scaffold Widget in a Button it can be Gesture Detector or Inkwell. Then add unfocus method in it.
GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: const Scaffold(
body: TextFormField(
decoration: OutlineInputBorder()),
);
I also needed to hide the keyboard when I clicked on a date picker (another widget)
During my experience, with GestureDetector keyboard hid itself when I clicked somewhere that is not a widget. It would not hide itself otherwise.
Simply changing GestureDetector
to
Listener and adding
onPointerDown: (PointerDownEvent event) => FocusManager.instance.primaryFocus?.unfocus(), gave me the solution.
So, in your instance, what you should do is, wrap the Button "Click me" with a Listener and give it onPointerDown ,that should hide your keyboard whenever you press the button.

Flutter: I want my screen to automatically scroll up when selecting Textfield so that my submit button is not hidden?

I'm currently wrapping my column widget in a SingleChildScrollView() and setting resizeToAvoidBototmInset: false on Scaffold(), yet the screen does not automatically scroll up when selecting the Textfields. Ideally, I want the submit button to show when user is inputting data into the second field. Currently it hides on some devices when the keyboard is visible.
Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: SafeArea(
child: Stack(
children: <Widget> [
CustomPaint(),
Column(children: <Widget>[
TextField(),
TextField(),
RaisedButton(),
])
]
)
)
)
)
This is what the current format looks like. I do not have a FocusNode() on the textfield and did think about raising the textfield based on when the keyboard is visible, but that disturbs my custom paint background and did not want to have that effect.
From a conceptual point of view, is there something I'm missing that is preventing the screen from automatically scrolling up.
Try with this code:
GlobalKey globalKey = GlobalKey();
...
TextField(
onTap: ()async{
await Future.delayed(Duration(milliseconds: 500));
RenderObject object = globalKey.currentContext.findRenderObject();
object.showOnScreen();
},
),
RaisedButton(
key: globalKey,
onPressed: (){},
),

Flutter keyboard hide not working on tab clicks

I have one application of tabbars. one tab have textfield. It shows keyboard. I want to hide keyboard after press ob any other tab. I used below code but its still not working on other tabs.
return new Scaffold(
key: _scaffoldKey,
resizeToAvoidBottomInset: false,
backgroundColor: blackColor,
body: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Stack(children: <Widget>[
_showForm(),
],)
),
);
you can use onTap under TabBar() like this:
TabBar(
onTap: (_) => FocusManager.instance.primaryFocus?.unfocus(),
tabs: [
tab1(),
tab2(),
)
this will make every tab unfocus the keyboard and move to other tab as well
Use FocusScope.of(context).unfocus() when tab change.
when you click to change tab write below line :
FocusScope.of(context).requestFocus(new FocusNode());

Floating Action Button centerDocked, overlapping any screen or dialogue?

I am using animated icons in my FloatingActionButton (FAB) at bottom navigation bar. But FAB overlapping any page or dialogue open from the BottomAppBar, how can I resolve this?
When I open a new page with Navigator.push, Navigator.pushNamed, modalBottomSheet or a dialogue, the fab overlapping them.
Only works when I use pushReplacementNamed to open a new page.
How can I show the modalSheet without the fab on it and a page using just pushNamed?
I use this reference.
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: _buildFab(context, model),
bottomNavigationBar: BottomAppBar(
color: CustomTheme.getThemeData(context).getAccentColor(),
shape: CircularNotchedRectangle(),
notchMargin: 4.0,
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
onPressed: () => _showModal(),
),
IconButton(
icon: Icon(Icons.home),
onPressed: () => {},
),
],
),
),
This is my FAB
And this happen when a show the modal or any page
Please I need your help..
I don't know what else to do. :-(
If this is happening with the Modal bottom sheet then try to increase the elevation of the bottom sheet. Like this
showModalBottomSheet(context: context, builder: (context) {
return AddressChangeBottomSheet(
title: "Change Area",
showAddress: false,
cityAreaList: list, onAddressChangeSubmit: () {
mainBloc.fetchUpdatedUser();
});
}, elevation: 10.0)

Flutter - click one RaisedButton and all RaisedButtons update

I am working on a calculator type app that has a lot of buttons on the screen. When I turn on dev tools to check repainting, I noticed that whenever one button is clicked, every button on the screen repaints. Instead of pasting tons of code in here, I created a demo app that shows what it is that I am doing. This is what the screen looks like:
Whenever any of the buttons are pressed, every button on the screen redraws.
This is the code that I'm using:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Button Testing'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
buttonPressed,
textAlign: TextAlign.center,
),
SizedBox(
height: 10.0,
),
RaisedButton(
child: Text('Button One'),
onPressed: () {
setState(() {
buttonPressed = 'Button One Was Pressed';
});
},
),
RaisedButton(
child: Text('Button Two'),
onPressed: () {
setState(() {
buttonPressed = 'Button Two Was Pressed';
});
},
),
RaisedButton(
child: Text('Button Three'),
onPressed: () {
setState(() {
buttonPressed = 'Button Three Was Pressed';
});
},
),
RaisedButton(
child: Text('Button Four'),
onPressed: () {
setState(() {
buttonPressed = 'Button Four Was Pressed';
});
},
),
],
),
),
),
);
}
I've tried breaking the button area out into a separate widget and nothing I've done matters. My question is, is there something else that I should be doing? Is this expected and acceptable behavior? Does it even matter that everything is redrawing whenever any buttons are tapped? I thought that in Flutter, only the things that needed to be redrawn were redrawn.
Whenever you call setState then it rebuild whole build method, so it is obvious that it rebuild RaisedButton.
You can avoid by using provider, Bloc and so on which will not rebuild whole build method. It will only change data.
It is totally depends on you that you want to accept it or not. If widget is not that much big than you can keep it according to me.
Redrawing widget every time is really not good practice but if it is not rebuilding very frequently or your application is not that much big then it is fine.
setState will rebuild all the screen ,
So you can avoid that by using Bloc it is a state controller which won't rebuild everything only what you need to rebuild you can use it from scratch or use the plugin bloc 1.0.0