Flutter 2: maxLength inside the textfield without using onChanged - flutter

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,
),
),

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.

How to show last line of one TextFormField with fixed number of lines in Flutter

I have a TextFormField with a fixed number of lines and when a screen load, this TextFormField already have more lines then a fixed number of lines that i defined,
and if i want to see the last line,
I need manually scroll it to the last line.
Is there a way to show automatically the last line of this TextFormField?
Container(
child: SingleChildScrollView(
child: TextField(
readOnly: true,
keyboardType: TextInputType.multiline,
maxLines: 9,
controller: chatController,
decoration: InputDecoration(
hintText: "Chat...",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
),
),
),
),
),
This appears to be a missing feature in the Flutter Framework, Someone has filed a bug to get it resolved: https://github.com/flutter/flutter/issues/9365
However site includes a work around. Please have a look at it.
make this public variable:
ScrollController scrollController = new ScrollController();
attach it to the TextField
TextField(
//...
scrollController: scrollController,
//...
),
put this into your initState function:
WidgetsBinding.instance.addPostFrameCallback((_) async {
scrollController.jumpTo(double.parse((9 * 17 * 1.9 /*number of lines * fontSize * 1.9 (you can of course experiment with this values)*/).toStringAsFixed(1)));
});
i hope it helped

Expand Textfield if available space, set minHeight with scroll if not

I've got a Column indide a Scaffold, and one of the Column's children is a TextField. I'd like the Textfield to expand and take all the available space, but if there is not enough space (basically when the keyboard shows up), I want the Textfield to be 3 lines height min and the Column to be scrollable so the focus on the Textfield works as intended.
I've tried a lot of different widgets, like Expand, IntrinsicHeight, LayoutBuilder, ConstrainedBox, SingleChildScrollView...
But none of the tested combination did work as expected...
The SingleChildScrollView page did help me a lot but none of the example match my situation :
https://docs.flutter.io/flutter/widgets/SingleChildScrollView-class.html
Scaffold(
body: Column(
children: <Widget>[
Text("Some\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nlong\ntext"),
RaisedButton(child: Text("Some button")),
Text("Second line"),
Expanded(
child: Padding(
//Use the expand parameter instead of padding + maxLines, once released : https://github.com/flutter/flutter/pull/27205
padding: const EdgeInsets.only(top: 10, bottom: 30),
child: TextField(
decoration: InputDecoration(
hintText: "Message...",
),
maxLength: 500,
maxLengthEnforced: true,
maxLines: 50,
),
),
),
Center(
child: RaisedButton(
child: Text('OK'),
onPressed: _send,
),
)
],
),
)
With that code the first part works fine : when not keyboard is shown, the Textfield is expanded as expected.
But when the keyboard shows up, the layout overflow (because there is no SingleChildScrollView).
EDIT : the new TextField.extends property helped a bit but didn't solved my issue...

TextField with animated hint / label

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

How do I add margins to my widget ? Understanding the effect of EdgeInsets

I am trying to wrap my head around ui placement in Flutter. So I currently have something that looks like this
I would like to add a little space b/w search Textfield and the button.
This is what the controlling part of my code looks like. I am trying to style my textFieldSearchBox so it has a little margin on the right, I tried trying to increase the Edge insets but it seems to increase the size of the TextField I don't know why? I know I could adding a padding element after TextField but I wanted to know what my other options are.Why does increasing the EdgeInsets in the decoration of textFieldSearchBox increase the size of the textbox? My ideal situation would be to add margin around all the borders of this textbox (LTRB).
Any suggestions?
TextField textFieldSearchBox = new TextField(
keyboardType: TextInputType.text,
controller: filterController,
autofocus: false,
decoration: new InputDecoration(
contentPadding: new EdgeInsets.fromLTRB(20.0, 10.0, 100.0, 10.0),
border:
new OutlineInputBorder(borderRadius: BorderRadius.only()),
),
);
var optionRow = new Row(
children: <Widget>[
new Expanded(child:textFieldSearchBox),
searchButton,
new IconButton(
icon: new Icon(Icons.filter),
onPressed: (){print("Called....");},
),
],
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Title goes here.."),
backgroundColor: Colors.lightBlueAccent,
),
body: new Container(
child:new Column(
children: <Widget>[
optionRow,
],
),
),
);
How to add margin to a widget
In Flutter we generally talk about adding Padding around a widget rather than margin. The Container widget does have a margin parameter, but even this just wraps it child (and any decoration that the child has) with a Padding widget internally.
So if you have something like this
and you want to add some space around the widget like this
then you just wrap the widget with Padding. This is easy to do if you put your cursor on the widget name and press Alt+Enter (or Option+Return on a Mac) in Android Studio. Then choose Add padding from the menu.
which gives you something like this
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"text",
style: TextStyle(fontSize: 20.0),
),
);
Meaning of EdgeInsets
When you are setting padding you can't directly use an integer or double. You have to specify the space (number of logical pixels) using the EdgeInsets. You can set all of the sides at once (as we saw in the example above), or you can set them individually like this:
Widget myWidget() {
return Padding(
padding: const EdgeInsets.only(
left: 40,
top: 20,
right: 40,
bottom: 20,
),
child: Text("text"),
);
}
Since in this example left and right are the same and top and bottom are the same, we can simplify EdgeInsets to
padding: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 20,
),
Using a Container to set padding and margin
An alternate method is to wrap your widget in a Container. The Container widget has both a padding and a margin property. (This would only be necessary, though, if you were also adding a decoration like background color or a border.)
Widget myWidget() {
return Container(
margin: EdgeInsets.all(30),
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.yellow,
border: Border.all(color: Colors.black),
),
child: Text(
"Flutter",
style: TextStyle(
fontSize: 50.0
),
),
);
}
Why does increasing the EdgeInsets in the decoration of textFieldSearchBox increase the size of the textbox ?
Because that padding is used for the internal padding. The one you see between the borders and the actual text.
My ideal situation would be to add margin around all the borders of this textbox (LTRB). Any suggestions ?
Wrap your TextField into a Padding. That is the ideal way to achieve the desired layout in flutter.
final textFieldSearchBox = new Padding(
padding: const EdgeInsets.only(right: 8.0),
child: new TextField(
keyboardType: TextInputType.text,
controller: filterController,
autofocus: false,
decoration: new InputDecoration(
contentPadding: new EdgeInsets.fromLTRB(20.0, 10.0, 100.0, 10.0),
border: new OutlineInputBorder(borderRadius: BorderRadius.only()),
),
),
);
You can put the component inside a padding, like this
var optionRow = new Row(
children: <Widget>[
new Expanded(child:textFieldSearchBox),
new Padding(padding: new EdgeInsets.all(20.0),child:button,),
new IconButton(
icon: new Icon(Icons.filter),
onPressed: (){print("Called....");},
),
],
);
Since the layout of your widgets is Row, why do not you add the mainAxisAlignment property to it like this:
mainAxisAlignment : MainAxisAlignment.spaceAround
Or
mainAxisAlignment : MainAxisAlignment.spaceBetween
Simply use
EdgeInsets.fromLTRB
For example:
padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
You can also use SizedBox if you want to avoid using Container
There are some widgets which allow that using a parameter, but in most cases You can wrap the Widget in a Padding widget like so.
From this
YourWidget(
....
)
To This
Padding(
padding: EdgeInsets.all(value),
YourWidget(
....
)
)
Where "all" can be replaced with the variant of your choice
In Flutter we generally talk about adding Padding around a widget rather than margin. The Container widget does have a margin parameter, but even this just wraps it child (and any decoration that the child has) with a Padding widget internally.strong text