TextFormField: Show suffixIcon only if text field is wide enough - flutter

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

Related

why the text inside the container does not show flutter

hello i'm new in flutter so inside a column a container then a sized box then another container and finally a button . the problem is the container which have the color amber does not show despite print is worked but i don't see the container on my screen . i wanna display a text inside that container if the email invalid any help ! thanks in advise
Container(
height: MediaQuery.of(context).size.height * 0.08,
margin: const EdgeInsets.symmetric(horizontal: 5),
decoration: BoxDecoration(
color: const Color(0xFFEFEDED),
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: TextFormField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
border: InputBorder.none,
),
),
),
),
const SizedBox(
height: 50,
),
InkWell(
onTap: () {
if (isValidEmail) {
emailsList.add(emailController.text);
box.write('emails', emailsList);
Navigator.of(context).pop();
}
if (!isValidEmail) {
Row(
children: [
Container(
color: Colors.amber,
),
],
);
print("test");
}
},
child: CustomButton("Ajouter", buttonColor, Colors.white)),
First of all, if you do not give any height or width to your container but only a color, it will never show. Why? Because it has no content meaning that the height and width by default are 0. So, I advise setting a height and width first.
Second, if you want to display a text if the field is not valid, you have something already existing. In your textField, you can give him an Inputdecoration and there you can access the parameters errorText. In order to have this working, you must use the formValidation with the widget Form and you kive him a key that is a formValidator.
Finally, if you do not want to use the errorText by default, you should put in the column something like this.
Column(
children:[
TextField(),
if (isEmailInvalid)
Text("This is the error Text")
]
)
With the "isEmailInvalid" which is a boolean.
I hope that all this information helps you. But if you have really a beginner, I advise to stick with the default setting of the TextField and take a look at the flutter documentation that is really interesting.
put a Row in Inkwell onTap? Row is not a function, you must return it in your build method.
return type of if statement must be 'Widget' . use 'return' before Container widget.

Flutter 2: maxLength inside the textfield without using onChanged

I am trying to find a way to use maxLength and put it inside of the textfield to have a nice rendering. However, I don't want to use the onChanged parameter because I would have to use a setState, but this not the good way to use it.
The parameter maxLength from the flutter's textfield is designed to do not update the state, so that every statefull widgets don't have to rebuild.
So I would like to put the 0/50 inside, at the end of the textfield, on the same line as Title.
From this :
To this :
So somebody have an idea of how to do it without using the parameter onChanged ?
Does flutter has implemented this functionality ?
Try with this, hope you get a solution.
TextField(
maxLength: 250,
buildCounter: (_, {currentLength, maxLength, isFocused}) => Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Container(
alignment: Alignment.centerLeft,
child: Text(currentLength.toString() + "/" + maxLength.toString())),
),
)
Also, Try with this,
TextField(
controller: nameController,
maxLength: 60,
prefixIcon: Icon(
Icons.account_circle,
color: Colors.black45,
),
),

How to use a responsive text form field widget in flutter?

I'm using "maxLine" as a length for the text form field but it does not fit in different size of phones, what should I put in order to make the length responsive.
The box border should fit on the size of the phone. https://i.stack.imgur.com/Wisa6.png. Here's my code, I'm using onTap in gesture detector to call that widget
Widget buildDescription() => TextFormField(
maxLines: MediaQuery.of(context).size.height.toInt(),
initialValue: widget.description,
style: TextStyle(color: Colors.black, fontSize: 18),
decoration: InputDecoration(
hintText: 'Tell us what you feel',
hintStyle: TextStyle(color: Colors.black54),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide(
color: Colors.grey.shade500,
width: 2,
style: BorderStyle.solid))),
validator: (description) => description != null && description.isEmpty
? "I'm here to listen. Don't hesitate to open up when you're ready"
: null,
onChanged: widget.onChangedDescription,
);
}
The following should make the TextFormField fill the screen and also make the number of lines unlimited.
Expanded(
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
expands: true,
),
)
You can put your TextFormField inside an Expanded widget, which will stretch it over the remaining screen space.
// expanded should be used inside rows or columns
return Column(
children: [
DateMarker(...),
HowDidIFailField(...),
// the expanded stretches the view over the remaining space
Expanded(
child: TextFormField(),
),
]
);
A thing to note is that when the keyboard appears, less space is available and the widget will shrink further. Make sure to test with that as well.

Flutter: Conflict between TextField's onTap and prefixIcon's onPressed

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

Flutter avoid focusing on TextField when clicking button inside

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.