For a TextField to work in Flutter, you need to give it a length. I've got a form working by wrapping the TextFields in Expandeds but I'd rather have the TextField resize based on the required width so that as the user types, the TextField expands. Here's my form code:
return Row(
children: <Widget>[
Expanded(
child: TextFormField(
keyboardType: TextInputType.number,
initialValue: snapshot.data[0].toString(),
textAlign: TextAlign.center,
decoration: InputDecoration(labelText: "Width", labelStyle: ),
),
),
Expanded(
child: TextFormField(
keyboardType: TextInputType.number,
initialValue: snapshot.data[1].toString(),
textAlign: TextAlign.center,
decoration: InputDecoration(labelText: "Height"),
),
),
],
);
And here is a picture of my form:
Simply add horizontal padding to the TextField like this
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(2,
(index) => Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: TextFormField(
keyboardType: TextInputType.number,
initialValue: index == 0 ? "3280" : "2464",
textAlign: TextAlign.center,
decoration: InputDecoration(
labelText: index == 0 ? "Width" : "Height"),
),
),
))),
),
);
You should set width for your text form field
for example:
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 100,
child: TextFormField(
keyboardType: TextInputType.number,
initialValue: "11",
textAlign: TextAlign.center,
decoration: InputDecoration(labelText: "Width"),
),
),
Container(
width: 100,
child: TextFormField(
keyboardType: TextInputType.number,
initialValue: "22",
textAlign: TextAlign.center,
decoration: InputDecoration(labelText: "Height"),
),
),
],
),
),
);
}
Related
I want to wrap the body inside a SingleChildScrollView widget but for some reason, it is not working. When I wrap the Container inside a SingleChildScrollView widget everything goes away. Any solution?
Scaffold(
body: Container(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Spacer(),
DisplayText(),
Spacer(),
Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Enter your username',
),
textInputAction: TextInputAction.next,
),
TextFormField(
decoration: InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Enter your password',
),
),
],
),
),
.
.
.
.
],
),
),
);
You can wrap the entire layout with Column and expand the child using Expanded widget then add SingleChildScrollView. Please remove Spacer, if you need space in-between widgets use SizedBox instead.
Scaffold(
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10,),
DisplayText(),
SizedBox(height: 10,),
Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Enter your username',
),
textInputAction: TextInputAction.next,
),
TextFormField(
decoration: InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Enter your password',
),
),
],
),
),
],
),
),
),
),
],
),
);
I have an authentication screen like this:
#override
Widget build(BuildContext context) {
final bottom = MediaQuery.of(context).viewInsets.bottom;
return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Column(
children: <Widget>[
SizedBox(height: 48),
Image.asset(
"assets/images/logo.png",
width: 132,
),
SizedBox(height: 48),
Form(
child: Column(
children: <Widget>[
AuthTextFormField(
icon: Icons.email_outlined,
labelText: 'Email',
keyboardType: TextInputType.emailAddress,
),
AuthTextFormField(
icon: Icons.lock_outline,
labelText: 'Password',
obscureText: true,
),
],
),
),
],
),
),
),
);
}
I have followed this answer, but it still did not work for me. The keyboard still covered the text field. Any idea?
Thank you.
[UPDATE]
I use the code written in the answer above (by Jay Jay). And, this is the screenshot:
Its covered like this:
This Code works fine for me, I have removed the image and added a Container on its place with some height.
Also I have made some changes to your Code,
Scaffold(
resizeToAvoidBottomPadding: true,
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Column(
children: <Widget>[
SizedBox(height: 48),
Container(
color: Colors.blue,
height: 500,
),
SizedBox(height: 48),
Form(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.email), labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.lock_outline),
labelText: 'Password'),
obscureText: true,
),
TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.email), labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.email), labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.email), labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
],
),
),
],
),
),
),
);
After trying it out, I think you should just add a height to your image.asset or better use a Container and specify the image in its decoration property and give the container a fixed height. It should all work correctly.
Here my code which works:
return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Column(
children: <Widget>[
SizedBox(height: 48),
Container(
height: 300,
color: Colors.red,
),
SizedBox(height: 48),
Form(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
icon:Icon(Icons.email),
labelText: 'Email'
),
keyboardType: TextInputType.emailAddress,
),
TextFormField(
decoration: InputDecoration(
icon: Icon(Icons.lock_outline),
labelText: 'Password'
),
obscureText: true,
),
],
),
),
],
),
),
),
);
I am new in Flutter so maybe my question will be basic for someone.
The problem is that in my app I want to hide TextField when CheckBox is unchecked. Next to a TextField is a button which should be static. My issue is that when I want to hide this TextField, button is shifting to the left side. I think that the best option is to show it to you
Before:
After:
This is the code I am using:
bool secondLayer = false;
void _secondLayer(bool value) => setState(() => secondLayer = value);
#override
Widget build(BuildContext context) {
return new Scaffold(
/*appBar: new AppBar(
title: new Text('Name Here'),
),*/
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: new Container(
padding: new EdgeInsets.all(32.0),
child: new Center(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
child: new Row(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
new TextField(
decoration: InputDecoration(
labelText: 'First Hidden Layer',
hintText: '25',
),
autocorrect: true,
autofocus: true,
keyboardType: TextInputType.number,
),
],
),
),
Expanded(
child: Column(
children: <Widget>[
new SizedBox(
width: 100,
child: new RaisedButton(onPressed: null, child: new Text('ADD DATA'),)
)
],
),
)
],
),
),
Container(
child: new CheckboxListTile(
value: secondLayer,
onChanged: _secondLayer,
title: new Text(
'Use Second Hidden Layer',
style: new TextStyle(
fontSize: 12
),
),
controlAffinity: ListTileControlAffinity.leading,
),
),
Container(
child: new Row(
children: <Widget>[
Visibility(
visible: secondLayer,
child: new Expanded(
child: Column(
children: <Widget>[
new TextField(
decoration: InputDecoration(
labelText: 'Second Hidden Layer',
hintText: '25',
),
autocorrect: true,
autofocus: true,
keyboardType: TextInputType.number,
),
],
),
),
),
Expanded(
child: Column(
children: <Widget>[
new SizedBox(
width: 100,
child: new RaisedButton(onPressed: null, child: new Text('OPTIONS'),)
)
],
),
)
],
),
),
Container(
child: new TextField(
decoration: InputDecoration(
labelText: 'Epochs',
hintText: '5000',
),
autocorrect: true,
autofocus: true,
keyboardType: TextInputType.number,
),
),
Container(
child: new TextField(
decoration: InputDecoration(
labelText: 'Learning Rate',
hintText: '0.00333',
),
autocorrect: true,
autofocus: true,
keyboardType: TextInputType.number,
),
),
Container(
padding: EdgeInsets.only(top: 20),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width/3,
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
border: Border.all(color: Color.fromRGBO(0, 0, 0, 100)),
),
child: new Text('data')
),
Container(
width: MediaQuery.of(context).size.width/3,
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
border: Border.all(color: Color.fromRGBO(0, 0, 0, 100)),
),
child: new Text('data')
)
],
)
)
],
),
)
)
)
);
It is because you didn't add any replacement property to your Visibility Widget.
Visibility(
visible: secondLayer,
child: Expanded(
child: Column(
children: <Widget>[
// your text field here
]
),
),
replacement: Expanded(child: Container()), // the widget which will fill the space when hiddden
)
Something like this should work as you replace your TextField with an empty Container inside an Expanded to fill your empty space.
You need to set the maintainSize property of the Visibility widget to true, it is used to decide "whether to maintain space for where the widget would have been." Source
You also need to set maintainAnimation and maintainState to true for maintainSize to work. Source
So your code will go from:
Visibility(
visible: secondLayer,
child: yourChildWidget
),
to:
Visibility(
visible: secondLayer,
maintainSize: true,
maintainAnimation: true,
maintainState: true,
child: yourChildWidget
),
I don't understood what's happening, but when the form got erros the helper text message is moving the TextFormField. I tried increasing the height but I could not fix.
Anyone knows what's happening?
Look the image:
Follow the code:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.centerRight,
child: CountryCodePicker(
showFlagMain: true,
onChanged: print,
initialSelection:
I18n.of(context).locale.countryCode,
favorite: ['+55', 'BR'],
showCountryOnly: false,
showOnlyCountryWhenClosed: false,
textStyle: TextStyle(
color: Colors.white, fontSize: 19.0),
flagWidth: 40.0,
)),
Container(
width: 200,
alignment: Alignment.center,
child: TextFormField(
keyboardType: TextInputType.phone,
controller: _phoneTextController,
inputFormatters: [
MaskTextInputFormatter(
mask: "(##) #####-####",
filter: {"#": RegExp(r'[0-9]')})
],
autocorrect: false,
autofocus: false,
style: TextStyle(
color: Colors.white, fontSize: 19.3),
cursorColor: Colors.yellow,
decoration: const InputDecoration(
border: InputBorder.none,
hintText: '(99) 99999-9999',
filled: true,
hintStyle: TextStyle(color: Colors.grey)),
validator: (String value) =>
phoneValidator(value),
))
],
),
SizedBox(height: 20),
RaisedButton(
child: Text('Send'),
onPressed: () {
if (this._form.currentState.validate()) {
print(this._unmask(this._phoneTextController.text));
}
},
)
],
Thanks.
Try to wrap the container in an expanded widget.
You can modify the crossAxisAlignment of your Row to CrossAxisAlignment.start and the TextFormField widgets will be aligned when showing error text. A sample of this is below.
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 250,
child: TextFormField(
validator: (value) {
if (value.isEmpty) {
return '$firstName must not be empty.';
}
return null;
},
controller: firstNameController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: firstName,
),
),
),
Container(
width: 250,
child: TextFormField(
validator: (value) {
if (value.isEmpty) {
return '$lastName must not be empty.';
}
return null;
},
controller: lastNameController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: lastName,
),
),
)
]),
),
How a TextField width can be resized automatically based on content in Flutter?
An example with 3 TextField which autoresize depending on the content :
Only place the TextField inside an Expanded that will be in a row.
return Scaffold(
body: Container(
padding: EdgeInsets.only(top: 50),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Padding(
child: new TextField(
onTap: () {//action of TextField
},
keyboardType: TextInputType.text,
decoration: InputDecoration(
border: InputBorder.none, hintText: 'Password'),
style: Theme.of(context).textTheme.body1,
),
padding: EdgeInsets.only(left: 40),
)),
IconButton(
icon: Icon(Icons.apps),
onPressed: () {//action of iconbutton
},
)
],
)
])),
);
Set the maxLines property of TextField to null. maxLines: null
TextField(
controller: new TextEditingController(
text: comment
),
maxLines: null,
style: TextStyle(
color: Colors.black,
fontSize: 12.0,
),
textAlign: TextAlign.left,
decoration: InputDecoration(
filled: true,
fillColor: HexColor('#ecedec'),
border: OutlineInputBorder(
borderSide:BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
),
)
I found the solution using the IntrinsicWidth class
IntrinsicWidth(
child: TextField(...
),