I am trying to recreate this textfield design
As you can see the label/hint text is centered when it is not focused and once in focus, the input text and the label/hint text are also centered within the border.
What I tried to recreate this design is first to create the textfield, remove all the borders, and wrap it with a container, and finally play with content padding but I either get text input text off-centered or I get the label/hint text off-centered.
Images below show how the label/hint is off-centered
BUT when in focus
Here sample code
Container(
height: 60,
padding: EdgeInsetsDirectional.only(
start: width * 0.038,
end: width * 0.038,
),
decoration: BoxDecoration(
border: Border.all(
color: state.hasError
? Constant.errorColor
: Constant.greyColor,
width: 1),
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: TextField(
inputFormatters: inputFormatter,
controller: controller,
onSubmitted: onSubmitted,
onChanged: state.didChange,
focusNode: focusNode,
textInputAction: textInputAction,
keyboardType: keyboard,
obscureText: obscure,
decoration: InputDecoration(
labelText: label,
alignLabelWithHint: true,
labelStyle: Constant.hintText.copyWith(
color: state.hasError
? Constant.errorColor
: Constant.greyColor,
fontSize: 14,
),
hintText: hint,
hintStyle: Constant.hintText.copyWith(fontSize: 14),
contentPadding: null,
// contentPadding: EdgeInsetsDirectional.only(
// bottom: 7.5,
// ),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
),
),
You could create a custom text box:
Container(
Column(
children: [
Text("insert label text", textAlign: TextAlign.start)
TextField(
...
// no labelText
// remove decorations
)
]
)
);
I currently have this TextFormField with a hintText:
the goal is to add Units inside the TextFormField, regardless of whether the user is typing or not. It should kinda look like this:
How to achieve this?
Also, how to center the value?
Here's my current code for the TextFormField:
TextFormField(
decoration: InputDecoration(
hintText: '0.0',
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0),
filled: true,
fillColor: Colors.white24,
floatingLabelBehavior: FloatingLabelBehavior.never,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
borderSide: BorderSide.none,
),
counterText: '',
),
),
TheTextFormField decoration can a suffixText property
TextFormField(
controller: c,
// align to center
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '0.0',
// show kg
suffixText: 'Kg',
)
Text can be centered using the textAlign property
One way is to use TextFormField and text inside row which is inside a container
something like this can help
Container(
child: Row(
children: [TextFormField(), Text('Kg')],
),
),
another way is that you can use
TextFormField(
decoration: InputDecoration(suffixText: 'Kg'),
),
but here the problem is that you will only get suffix text when the TextFormField is enabled, one workaround you can try to make it always visible is to use autovalidate property like
TextFormField(
autovalidateMode: AutovalidateMode.always,
decoration: InputDecoration(suffixText: 'Kg'),
),
I have not tested this autovalidateMode but it should work properly.
I have a custom text field but as shown in the picture, the bottom text fields looks so vague and empty, I'd like to keep the hint showing even if the field is not focused, how do I achieve that in flutter?
here is my widget code:
Container(
margin: EdgeInsets.all(20),
child: TextFormField(
autofocus: true,
textAlign: TextAlign.right,
decoration: InputDecoration(
enabledBorder: const OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff0E9447), width: 2.0),
),
focusedBorder: const OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff0E9447), width: 2.0),
),
hintText: AppStrings.email,
labelText: AppStrings.email,
alignLabelWithHint: true,
hintStyle: TextStyle(color: AppColors.primaryColorLight),
),
),
),
If you would like the label to be visible at the top of the TextField, and the hint displayed at the same time you can simply add:
floatingLabelBehavior: FloatingLabelBehavior.always
to the TextFields InputDecoration (decoration).
(At the time of writing this, there is a bug that will only show the hint and suffix upon focus, this has been fixed in a very recent PR and will be available shortly, see GitHub issue)
Full Example
TextFormField(
controller: textController,
style: theme.textTheme.bodyText2,
keyboardType: keyboardType ?? TextInputType.number,
enableInteractiveSelection: false,
decoration: InputDecoration(
labelText: labelText,
labelStyle: theme.textTheme.headline6,
suffixText: suffixText ?? '',
border: OutlineInputBorder(
borderSide:
BorderSide(color: theme.textTheme.bodyText2.color, width: 2),
),
hintText: '0.0',
floatingLabelBehavior: FloatingLabelBehavior.always),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
onChanged: (String text) => onChange(text),
);
Ideally in Flutter you cannot do this as both hintText and labelText behave in two different ways. labelText is shown as hintText as long as the user does not focus on it. As soon as the user clicks on the TextField, the labelText animates to a specific position whereas a hintText remains visible until the user types something.
So using labelText and hintText together, does not make any sense as the TextField will wipe of the hintText while animating the label.
However with some extra effort, you can use Stack widget to solve your problem.
Declare a class variable (a variable within the concerned class, outside any block of code) to store a TextEditingController.
TextEditingController _controller;
And initialize in your class' initState(),
_controller= TextEditingController();
Solution Code:
Container(
margin: EdgeInsets.all(20),
child: Stack(
children : <Widget>[
TextFormField(
autofocus: true,
textAlign: TextAlign.right,
decoration: InputDecoration(
enabledBorder: const OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff0E9447), width: 2.0),
),
focusedBorder: const OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff0E9447), width: 2.0),
),
labelText: AppStrings.email,
alignLabelWithHint: true,
hintStyle: TextStyle(color: AppColors.primaryColorLight),
),
),
(_controller.text=="")
?
Text(
AppStrings.email,
style: TextStyle(
color: Colors.grey
// Style it according to your requirement / To make it look like hintText
),
)
:
Container();
],
),
),
Basic Logic of the above code: If the TextField does not have any text then display the (hint) Text
widget else don't display anything.
There is a way around this.
Use the labelText property and set floatingLabelBehavior: FloatingLabelBehavior.never.
This way you will always see the hint and when the User clicks on the TextField, it goes away.
How to customise TextField's width and height?
To adjust the width, you could wrap your TextField with a SizedBox widget, like so:
const SizedBox(
width: 100.0,
child: TextField(),
)
I'm not really sure what you're after when it comes to the height of the TextField but you could definitely have a look at the TextStyle widget, with which you can manipulate the fontSize and/or height
const SizedBox(
width: 100.0,
child: TextField(
style: TextStyle(fontSize: 40.0, height: 2.0, color: Colors.black),
),
)
Bear in mind that the height in the TextStyle is a multiplier of the font size, as per comments on the property itself:
The height of this text span, as a multiple of the font size.
When [height] is null or omitted, the line height will be determined
by the font's metrics directly, which may differ from the fontSize.
When [height] is non-null, the line height of the span of text will be a
multiple of [fontSize] and be exactly fontSize * height logical pixels
tall.
Last but not least, you might want to have a look at the decoration property of you TextField, which gives you a lot of possibilities
EDIT: How to change the inner padding/margin of the TextField
You could play around with the InputDecoration and the decoration property of the TextField. For instance, you could do something like this:
const TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 40.0),
),
)
I think you want to change the inner padding/margin of the TextField.
You can do that by adding isDense: true and contentPadding: EdgeInsets.all(8) properties as follow:
Container(
padding: EdgeInsets.all(12),
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Default TextField',
),
),
SizedBox(height: 16,),
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Densed TextField',
isDense: true, // Added this
),
),
SizedBox(height: 16,),
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Even Densed TextFiled',
isDense: true, // Added this
contentPadding: EdgeInsets.all(8), // Added this
),
)
],
),
)
It will be displayed as:
Screenshot:
You can do it in many ways:
Using maxLines + expands:
SizedBox(
width: 240, // <-- TextField width
height: 120, // <-- TextField height
child: TextField(
maxLines: null,
expands: true,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(filled: true, hintText: 'Enter a message'),
),
)
Using just maxLines:
Widget _buildTextField() {
final maxLines = 5;
return Container(
margin: EdgeInsets.all(12),
height: maxLines * 24.0,
child: TextField(
maxLines: maxLines,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(filled: true, hintText: 'Enter a message'),
),
);
}
This answer works, but it will have conflicts when the input field is in error state, for a better approach and a better control you can use this.
InputDecoration(
isCollapsed: true,
contentPadding: EdgeInsets.all(9),
)
If you want to increase the height of TextFormField dynamically while typing the text in it. Set maxLines to null. Like
TextFormField(
onSaved: (newText) {
enteredTextEmail = newText;
},
obscureText: false,
keyboardType: TextInputType.emailAddress,
validator: validateName,
maxLines: null,
// style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),
hintText: "Enter Question",
labelText: "Enter Question",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
),
Wrap TextField in SizedBox for the width
SizedBox(
height: 40,
width: 150,
child: TextField(),
)
You can try the margin property in the Container. Wrap the TextField inside a Container and adjust the margin property.
new Container(
margin: const EdgeInsets.only(right: 10, left: 10),
child: new TextField(
decoration: new InputDecoration(
hintText: 'username',
icon: new Icon(Icons.person)),
)
),
If you use "suffixIcon" to collapse the height of the TextField add:
suffixIconConstraints
TextField(
style: TextStyle(fontSize: r * 1.8, color: Colors.black87),
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.symmetric(vertical: r * 1.6, horizontal: r * 1.6),
suffixIcon: Icon(Icons.search, color: Colors.black54),
suffixIconConstraints: BoxConstraints(minWidth: 32, minHeight: 32),
),
)
simply wrap the TextField() in SizedBox() and give the height of the sized box
use contentPadding, it will reduce the textbox or dropdown list height
InputDecorator(
decoration: InputDecoration(
errorStyle: TextStyle(
color: Colors.redAccent, fontSize: 16.0),
hintText: 'Please select expense',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(1.0),
),
contentPadding: EdgeInsets.all(8)),//Add this edge option
child: DropdownButton(
isExpanded: true,
isDense: true,
itemHeight: 50.0,
hint: Text(
'Please choose a location'), // Not necessary for Option 1
value: _selectedLocation,
onChanged: (newValue) {
setState(() {
_selectedLocation = newValue;
});
},
items: citys.map((location) {
return DropdownMenuItem(
child: new Text(location.name),
value: location.id,
);
}).toList(),
),
),
Set minLines: null, maxLines: null and expands:true to let the TextField fill the height of its parent widget:
Container(
child: TextField(
minLines: null,
maxLines: null,
expands: true
)
)
Refere to these docs for the same:https://api.flutter.dev/flutter/material/TextField/expands.html
And for width, you can do this:
Container(
width: 100,
child: TextField(
)
)
to let the TextField fill its parent widget's width(100 pixels in this case)
Adjust Height using contentPadding instead of SizeBox or Container
Container(
width: width * 0.85,
child: TextFormField(
textInputAction: TextInputAction.next,
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 10), //Imp Line
isDense: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(
width: 0.5,
color: Constants.secondaryColourLight,
)),
),),)
80k ka code hein 80k ka
Finally, I got my solution using this trick.
Provide Height and width of sizedbox and set expand the property to true. Also, set maxLines to null and minLines to null.
SizedBox(
height: SizeConfig.screenWidth * 0.1377,
child: TextFormField(
validator: validator,
enabled: isEnabled,
expands: true,
maxLines: null,
minLines: null,
),
);
TextField( minLines: 1, maxLines: 5, maxLengthEnforced: true)
int numLines = 0;
Container(
height: numLines < 7 ? 148 * WidgetsConstant.height: numLines * WidgetsConstant.height * 24,
child: TextFormField(
controller: _bodyText,
maxLines: numLines < 7 ? 148 : numLines,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
onChanged: (String value) {
setState(() {
numLines = '\n'.allMatches(value).length + 1;
});
},
),
),
The perfect way to get rid of padding is to use InputDecoration.collapsed.
It wraps the GestureDetector with a Container and decorates the Container with as much Padding, Border, and Decoration as needed.
GestureDetector(
onTap: () => _focusNode.requestFocus(),
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(4),
),
child: TextField(
focusNode: _focusNode,
decoration: const InputDecoration.collapsed(
hintText: 'Search...',
border: OutlineInputBorder(
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
),
),
),
);
To display an icon, change the Container child to Row, and use Icon and a TextField wrapped with Expanded.
To increase the height of TextField Widget just make use of the maxLines: properties that comes with the widget. For Example:
TextField(
maxLines: 5
) // it will increase the height and width of the Textfield.
You can simply wrap Text field widget in padding widget.....
Like this,
Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0),
child: TextField(
cursorColor: Colors.blue,
decoration: InputDecoration(
labelText: 'Email',
hintText: 'xyz#gmail.com',
//labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(width: 2, color: Colors.blue,)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(width: 2, color: Colors.green)),
)
),
),
You can change max
minLines: 4,
maxLines: 6,
Provide a maxLines and add a BoxConstraints with width and height in InputDecoration.
TextField(
maxLines: 10,
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
constraints: BoxConstraints.tightFor(width: 300, height: 100),
),
);
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
constraints: BoxConstraints(maxHeight:48,maxWidth: 327,),
),
);