How to freeze label in TextField? - flutter

I have label in the top left corner of my TextField. I want the user to be able to see the hint always (and after that he filled the form), but it disappears when I tap.
#override
Widget build(BuildContext context) {
return TextField(
decoration: InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.never,
label: Align(
alignment: Alignment.topLeft,
child: Text(
_text,
textAlign: TextAlign.left,
style: const TextStyle(fontSize: 15),
)),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(10))),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(10)),
)));
}

You can achieve this behavior by using the hintText property in the InputDecoration class. The hintText property provides a text hint that is displayed in the input field when it is empty. The hint text disappears as soon as the user starts typing and reappears if the text field is emptied. Here's the updated code:
#override
Widget build(BuildContext context) {
return TextField(
decoration: InputDecoration(
hintText: _text,
floatingLabelBehavior: FloatingLabelBehavior.never,
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(10))
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(10)),
)
),
);
}

The material design suggest to use the labelText property on the InputDecoration. Maybe you have already tried and dismissed it.. but I'm checking just in case... have you tried that?
This will be the typical outcome:

If you do not want to go with hintText, you can make a stack where the first child is the ’TextField’ and the other is Positioned for your text.

Related

Change prefix icon color of text form field in flutter on clicking the field

I have a name form field in flutter app. There's a prefix icon in it. When I click the form field the color of icon changes to blue, rather I want to change it to green. How can I do that, can anyone please guide me? This is its code :
TextFormField(
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.green, width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
prefixIcon: const Icon(Icons.person),
hintText: "Name",
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
),
);
Flutter's way to go is to use resolveWith. You can check the current state to check if the text field is focused, shows an error, etc. And depending on that you set the color.
From the docs (https://api.flutter.dev/flutter/material/InputDecoration-class.html):
final ThemeData themeData = Theme.of(context);
return Theme(
data: themeData.copyWith(
inputDecorationTheme: themeData.inputDecorationTheme.copyWith(
prefixIconColor:
MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.focused)) {
return Colors.green;
}
if (states.contains(MaterialState.error)) {
return Colors.red;
}
return Colors.grey;
}),
)),
child: TextFormField(
initialValue: 'abc',
decoration: const InputDecoration(
prefixIcon: Icon(Icons.person),
),
),
);
Use Theme color to change then define the focus node to determine when the field is on focus in order to apply these color changes
...
FocusNode _fieldNode = FocusNode(); //<-Define this then
...
TextFormField(
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.green, width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
prefixIcon: Icon(Icons.person,
color: _fieldNode.hasFocus
? Theme.of(context).primaryColor
: Colors.purple)),
hintText: "Name",
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
),
);

Bug in TextField in flutter

When I tap on Text Field and write from keyboard then I click done,
all data from Text Field was cleared.
This is my code:
TextField(
controller: controller,
keyboardType: textInputType,
decoration: InputDecoration(
hintText: hintText,
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 0.5),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black,
width: 1,
),
),
),
)
my controller:
TextEditingController controller = TextEditingController();
I'm guessing this is a stateless widget, and you're instantiating the TextEditingController in it. Closing the keyboard is causing a rebuild and you're losing the state, and a new controller is being created. You'll want to use a stateful widget and put the TextEditingController in state.

Flutter Forms Validation on change

Hey maybe someone can help me to figure out how implement proper form validation in Flutter.
So basically in InputDecoration we have
decoration: InputDecoration(
// focusedBorder: OutlineInputBorder(
// borderSide: BorderSide(color: Colors.white, width: 3.0),
// ),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red, width: 3.0),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.greenAccent, width: 3.0),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red, width: 3.0),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white, width: 3.0),
),
labelText: 'Email',
// errorText: !_isValid ? "Invalid Email" : null,
labelStyle: TextStyle(color: Colors.white),
prefixIcon: Padding(
padding: const EdgeInsets.only(top: 10, left: 13),
child: FaIcon(
FontAwesomeIcons.at,
color: Colors.white,
size: 25,
),
),
),
So problem is that I can't understand how to set regular border on form when it is not touched , than when it's touched , on each input it has to validate input and set error if not valid. I know that on TextFormField i can pass onchange function and do the validation
onChanged: (value) {
if (value.isEmpty || !value.contains('#')) {
setState(() {
_isValid = false;
});
print('invalid');
} else {
setState(() {
_isValid = true;
});
}
with this approach I have issue, first I have to set initial value of _isValid and in this case when form is opened and not touched it's already are enabled or with error depending on initial value of _isValid.
I came from web and worked with Angular and there we have reactive forms, maybe someone explain how to achieve similar behavior in flutter?
validator: (value) {
if (enter code herevalue.isEmpty || !value.contains('#')) {
return "incorrect format";
}
1 create a global form key
2 warp your widget inside a Form widget
3 pass your global key to the key parameter of your Form widget
4 and use this line on button click
5 _yourFormKey.CurrentState.Validate();

In Flutter, How can I change TextFormField validation error line style?

I want to set a different color for the error line created by the validator in TextFormField but I don't know how...
Change the color and the width to your likings providing errorBorder and focusedErrorBorder inside InputDecoration as decoration for TextFormField:
TextFormField(
decoration: InputDecoration(
focusedErrorBorder:UnderlineInputBorder(
borderSide: const BorderSide(color: Colors.blue, width: 2.0))
errorBorder: UnderlineInputBorder(
borderSide: const BorderSide(color: Colors.blue, width: 2.0),
),
),
),

How to always show hint in text field not only when it is clicked in flutter?

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.