Related
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,
),
),
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.
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.
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
I have a textfield and need to have multi-line as below so that the text wraps, however it takes up the space of all the lines that is defined in maxLines. I want to be able to have it look like 1 line and expand as the text wraps. Any ideas of how to do this is flutter?
new TextField(
decoration: const InputDecoration(
hintText: 'Reply',
labelText: 'Reply:',
),
autofocus: false,
focusNode: _focusnode,
maxLines: 1,
controller: _newreplycontroller,
keyboardType: TextInputType.text,
),
Set maxLines to null and it will auto grow vertically.
It's documented (but not entirely clearly) here (edit: I've created a PR to update this, which I should've done to begin with for this question ;). To figure it out I ended up looking at the code for TextField and its superclass(es), seeing what the behavior would be if set to null.
So your code should be as follows:
new TextField(
decoration: const InputDecoration(
hintText: 'Reply',
labelText: 'Reply:',
),
autofocus: false,
focusNode: _focusnode,
maxLines: null,
controller: _newreplycontroller,
keyboardType: TextInputType.text,
),
If you're trying to make it autogrow horizontally, you probably shouldn't - at least not based on the text content. But I'm asuming you want to make it autogrow vertically.
Using this should do the trick:
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 20,
maxLength: 1000,
Adding the minLines and MaxLines is important in order to get the required behaviour, whereas maxLength is a treat!
Maybe too late, but better late than never!
As shown in the first answer, setting maxLines to null will do the trick. However this would allow the textfield to grow infinitely.
To have more control, set minLines to 1 and maxLines as needed.
Hope this helps!
Code Sample:
TextField(minLines:1,maxLines:8)
The accepted answer works great for growing vertically. If you'd like the TextField to start small and expand horizontally as the user types, you can do the following:
IntrinsicWidth(
child: TextField(...
),
In my case I wanted it centered on the screen (horizontally), so I did:
Center(
child: IntrinsicWidth(
child: TextField()
)
)
Setting to null was working the same as setting to 1 (it grows horizontally just one line).
I think you have to set minLines and maxLines.
I'm using minLines: 1 and maxLines: 2 and when the first line reaches the end it expands another line. When the second line reaches the end it scroll the second to the first and creates the third line. So you will have to set maxLenght too.
If you want to set a predefined height, use expands: true:
SizedBox(
height: 200,
child: TextField(
decoration: InputDecoration(hintText: 'Enter a message'),
maxLines: null,
expands: true,
),
)
You can simply use this;
TextField get _text => TextField(
maxLines: null,
decoration: InputDecoration(
constraints: BoxConstraints(
maxHeight: responsiveHeight,
maxWidth: responsiveWidth),
contentPadding: EdgeInsets.symmetric(
horizontal: responsiveHorizontalPadding,
vertical: responsiveVerticalPadding),
disabledBorder: InputBorder.none,
border: InputBorder.none,
enabledBorder: InputBorder.none,
isDense: false,
));
#Rabi Roshan,
As shown in the first answer, setting maxLines to null will do the
trick. However this would allow the textfield to grow infinitely.
To have more control, set minLines to 1 and maxLines as needed. Hope
this helps!
Thank you so much!
I also prefer this version much more because it will only expand if the user inputs more than one line. And if it exceeds the maxLines, it will scroll vertically which is what should normally happen and what all big Chat Apps use.
textfield and need to have multi-line as below so that the text wraps, however it takes up the space of all the lines that is defined in maxLines. I want to be able to have it look like 1 line and expand as the text wraps
Container(
child: new TextField (
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 10,
decoration: new InputDecoration(
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(10.0),
),
),
filled: true,
hintStyle: new TextStyle(color: Colors.grey[800]),
hintText: "Type in your text",
fillColor: Colors.white70),
),
padding: new EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 16.0),
);