I have a widget that looks like this:
The code looks like this:
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your address or ZIP code',
hintStyle: TextStyle(fontSize: 18),
suffixIcon: IconButton(
icon: Icon(Icons.gps_fixed),
onPressed: () {
...
},
),
),
),
The behavior I want is that when the user clicks on the GPS button, instead of having the keyboard pop up, the TextField should become temporarily read-only and be filled with the current address after we get a response from some API.
The problem is, the way I wrote the code causes the TextField to gain focus when the GPS button is clicked. The click handler then disables the TextField to do async query, which causes the keyboard to disappear immediately. This creates a very janky animation.
Is there a way to make the TextField NOT gain focus when the GPS button is clicked?
This suffixIcon for the textfield is a part of it, If you click the suffixIcon, it's also performing click on the textfield. This is the reason why you are getting your keyboard poped up.
Solution:
Wrap your textfield into a Stack, and make sure IconButton is the last child of it. This performs click on your IconButton instead of gaining focus in textfield.
Stack(
alignment: Alignment.centerRight,
children: <Widget>[
TextField(),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
},
),
],
)
It is a known bug, issue has ben opened on github , and closed due to inactivity... You can take a look at that issue, there are some workarounds posted by users, they mainly revolve around stacks. I'm guessing that is where Suman's answer stems from :).
I propose a different approach, simply separate the button from the TextField.
Something like this:
Row(
children: <Widget>[
Expanded(
flex: 1,
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your address or ZIP code',
hintStyle: TextStyle(fontSize: 18),
),
)),
Expanded(
flex: 0,
child: IconButton(
icon: Icon(Icons.gps_fixed),
tooltip: 'Get a gpx fix',
onPressed: () {
print("do something");
}),
),
],
)
);
I personally prefer to have the button outside the text field because IMHO it conveys that it is a button more so than when having it inside. When inside it looks like it is just an icon that describes the field. Anyhow that is just personal preference, you can add border around both elements if that is what you prefer by wrapping both in a container and placing the decoration on the container.
Related
When the prefixicon is clicked, onTap will be called back automatically. How to ban it?
child: TextField(
onTap: ReplyController.to.onClickTextField,
decoration: InputDecoration(
prefixIcon: IconButton(
onPressed: ReplyController.to.openEmojiField,
color: Colors.black,
icon: Icon(CupertinoIcons.smiley),
),
),
),
You can add a FocusNode to the TextField to have access whether the field is actually focused. And now if you want to ignore the onTap when textfield has focus you could modify the onTap such as onTap: !focusNode.hasFocus? ReplyController.to.onClickTextField : null
I am Facing Some Issues on this Topic. I have a Material Button. as you can see in the Code below there is an "Emoticon" icon is Set for it.
MaterialButton(
onPressed: () {},
// color: Colors.transparent,
child: Icon(
Icons.emoji_emotions_outlined,
color: Colors.black54,
size: 35,
),
shape: CircleBorder(),
padding: EdgeInsets.all(16),
),
],
),
I also Have a Text Field which Looks like, this, (below),
TextFormField(
// autofocus: true,
decoration: InputDecoration(
labelText: 'Write Task',
// border: OutlineInputBorder(),
prefixIcon: Icon(Icons.add),
),
),
After the user is done writing I need to Show up this List of emojis [π,π,π,π,π,π
,π€£] One by one in the Delay of One Second. inside the Material Button, Place Above, in the place of Icon.
I have a Material Button
I have an Icon Inside it.
I also Have a Text Field
After TextField is Done Writing, I need to Show List of emojis [π,π,π,π,π,π
,π€£]
I want to replace the Icon in the Material Button.
And I want to Show a Slide Show of These Emojis Except the Button's Icon
Also If user Clicks on Emoji the Emoji Gets Locked, or Store in Some kind of Variable
I really want to Seek Help at this.
Two things here,
Initially one icon is shown in material button. As per the user's interaction the icon will be changed. To achieve this, create instance of IconData (as Icon accepts IconData) and initially set the default icon. You can set the selected IconData to the variable whenever user selects another icon.
I don't know whether this traditional icons are there in Material Icons library or not. Check font_awesome_flutter otherwise.
I have a TextFormField component with a suffixIcon. But some of my input fields are quite some, as they only accept 2 or 3 characters. I want to hide the suffixIcon automatically if the text field is too small. Is this possible?
TextFormField(
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(
Icons.clear,
color: ThemeColors.iconColor,
),
onPressed: () {
_controller.clear();
},
)
),
controller: _controller
)
Edit:
The width of the text field is not fixed - I don't know its width. Usually, the text field is integrated into a flexible layout, e.g. in Rows.
So, in fact, I need to know the width of a flexible text field.
You can use the constraints provided by the LayoutBuilder and update the UI accordingly. You can use constraints.maxWidth and compare it with your value
Your code will be updated as follows
LayoutBuilder(builder: (context, constraints) {
print(constraints.maxWidth);
return TextFormField(
decoration: InputDecoration(
suffixIcon: constraints.maxWidth > YOUR_VALUE ? IconButton(
icon: Icon(
Icons.clear,
color: ThemeColors.iconColor,
),
onPressed: () {
_controller.clear();
},
) : null,
)
);
});
I hope it helps!
Yes just wrap you widget which you want to hide with Visibility and add condition to check whether the input field length is greater or smaller
how can i make the user input to stay and not disappear after users done so next time the user want to update the text they get to clear the text fileds manually!
Padding(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextField(
style: TextStyle(fontSize: 18.0),
decoration: InputDecoration(
labelText: 'option',
),
onChanged: (input) => _alOne2 = input,
),
)
best regards
Solved the issue by changing TextField to TextFormField and using its initial value .i am using several fields in the same page and in that case had to create a Controller for each field.
I want to implement a form containing TextFields. Each field has a label / hint. I want the hint to animate and become a label when the user starts typing. This is a standard Material design pattern, so I expected it to be implemented by the standard Widgets.
Something like this:
It turns out to be very simple.
InputDecoration has a labelText parameter, which does what I wanted.
E.g.
TextField(decoration: InputDecoration(labelText: 'Full name')),
In Flutter, both hint and label are behaving in two different way that hintText will be shown as fixed but the labelText will be(double acting) shown as hint which is animating to the top when the cursor is getting focused.
TextField(decoration: InputDecoration
(
labelText: "Animatable hint",
hintText: "Inanimate hint"
)
)
Difference between labelText and HintText.
labelText : Shows label top of the input field, if it's empty or unfocused. When it get focus, labelText moves to above the input field.
hintText: just shows hint to the user.
TextField(decoration: InputDecoration(labelText: 'labelText'),),
TextField(decoration: InputDecoration(hintText: 'hintText'),),
TextField(decoration:InputDecoration(hintText: 'both', labelText: 'both'),),
more information - TextFormField placeholder
Also it's a good way to make your own Method or widget.(So you can reuse code later)
Example:
//your generator method or you can make your own widget class if you want that.
Widget _entryField(String title, {bool isPassword = false}) {
return Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
SizedBox(
height: 10,
),
TextField(
obscureText: isPassword,
decoration: InputDecoration(
//labelText: title , // you can change this with the top text like you want
hintText: "Please enter your $title" ,
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
filled: true))
],
),
);
}
==============
Edit:
As mentioned by #Evin1_ below.
After reading this article Splitting widgets to methods is a performance antipattern/Iiro Krankka
I found it's better to use StatelessWidget to split your code and functions only for doing Operations.
the reason:
This way, you wonβt be rebuilding your static widget trees multiple times for nothing but wasted CPU cycles.
If you really prefer building your widget trees with methods, you might want to take a look at a package called functional_widget by Remi Rousselet.
Also others comments for more information about this topic here difference between functions and classes to create reusable widgets