I have set a color to an icon in a TextFormField, but the color only comes when the TextFormField is focused.
How do I set it so that upon a setState() the icon stays 'focused' or colored?
try this:
bool _textIsEmpty = true;
TextEditingController _controller= TextEditingController();
... // rest of your code
TextField(
controller: _controller,
decoration: InputDecoration(
icon: Icon(
Icons.abc,
color: _textIsEmpty ? Colors.transparent : Colors.pink,
),
),
onChanged: (value) {
setState(() {
_textIsEmpty = value.isEmpty;
});
},
),
Basically what I'm trying to do is to supply an initial value (grey) to a text field and once the user clicks the text field, the initial value is automatically cleared and the user input should be black. Currently my code is like this.
TextEditingController _controller;
FocusNode _focusNode;
#override
void initState() {
super.initState();
_controller = TextEditingController(text: 'Search');
_focusNode = FocusNode()..addListener(_onFocus);
}
#override
void dispose() {
_focusNode.dispose();
_controller.dispose();
super.dispose();
}
void _onFocus() {
if (_focusNode.hasFocus) _controller.clear();
}
Widget _buildSearchBox() {
return CupertinoTextField(
controller: _controller,
focusNode: _focusNode,
style: TextStyle(
fontSize: 17,
color: _focusNode.hasFocus
? CupertinoColors.black
: CupertinoColors.systemGrey,
),
decoration: BoxDecoration(
color: CupertinoColors.systemGrey6,
),
);
}
I know it doesn't work because: (a) everytime the user types something, does something else and clicks the text field again, his input is cleared (b) I hope only the initial value is grey, but once the user does something else, his input also becomes grey.
Can anyone help me with it? Thanks.
From what I understood from the question, one way you can do this is something like this
FocusNode _focusNode;
#override
void initState() {
super.initState();
_focusNode = FocusNode()..addListener(_onFocus);
}
void _onFocus() {
setState((){});
}
Widget _buildSearchBox() {
return CupertinoTextField(
placeholder: "Search",
focusNode: _focusNode,
style: TextStyle(
fontSize: 17,
color: _focusNode.hasFocus
? CupertinoColors.black
: CupertinoColors.systemGrey,
),
decoration: BoxDecoration(
color: CupertinoColors.systemGrey6,
),
);
}
#override
void dispose() {
_focusNode.dispose();
super.dispose();
}
Add a placeholder field see you cannot style it, individually as
It is a lighter colored placeholder hint that appears on the first line of the text field when the text entry is empty.
Defaults to having no placeholder text.The text style of the placeholder text matches that of the text field's main text entry except a lighter font weight and a grey font color.
CupertinoTextField(
placeholder: "Enter Email", //Add this and your work is done
controller: _controller,
focusNode: _focusNode,
style: TextStyle(
fontSize: 17,
color: _focusNode.hasFocus
? CupertinoColors.black
: CupertinoColors.systemGrey,
),
decoration: BoxDecoration(
color: CupertinoColors.systemGrey6,
),
);
I have a TextField widget which has default background color red.
I want to change the background color to blue when the TextFiled is focused. But I can't do that.
There are three relative properties about the color I have tried.
filled: true,
fillColor: Colors.red,
focusColor: Colors.blue,
The result is only filled is set to true, the fillColor worked and the focusColor never work.
Can you tell me what to do?
You need to use a FocusNode on your TextField and a color variable to change the color:
Declarations
FocusNode _textFieldFocus = FocusNode();
Color _color = Colors.red;
#override
void initState() {
_textFieldFocus.addListener((){
if(_textFieldFocus.hasFocus){
setState(() {
_color = Colors.blue;
});
}else{
setState(() {
_color = Colors.red;
});
}
});
super.initState();
}
Widget
TextField(
decoration: InputDecoration(
fillColor: _color,
filled: true
),
focusNode: _textFieldFocus,
),
I am trying to change my labelText color when focused. I can change the text color but not when focused.
I have tried all the hint text colors and label text colors, but nothing helps.
Container(
padding: EdgeInsets.fromLTRB(15, 10, 15, 0),
child: TextFormField(
cursorColor: Colors.lightGreen,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'Phone Number',
hintText: 'Enter a Phone Number',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.lightGreen
)
),
border: OutlineInputBorder(
borderSide: BorderSide()
),
)
),
),
Here are images of what is happening:
You'd need to have a way determine its focus state and then create a conditional for its color based off of that. This is where a focusNode would be helpful. Construct a new FocusNode off the widget creation, use that as the focusNode property in the TextFormField. Then in color property of the TextStyle property of the TextFormField you could add something like:
FocusNode myFocusNode = new FocusNode();
...
return TextFormField(
focusNode: myFocusNode,
decoration: InputDecoration(
labelText: 'test',
labelStyle: TextStyle(
color: myFocusNode.hasFocus ? Colors.blue : Colors.black
)
),
);
EDIT : Just a quick note, you'll probably need to make sure this is in a StatefulWidget and then add a listener to the focusNode you created and call setState on any events on that focusNode. Otherwise you wont see any changes.
The Summary
You might want to check out Flutter Cookbook's Focus and text fields recipe.
Essentially, we have to:
Create a FocusNode property.
Add initialization and disposal to it.
Add it to the TextFormField.
Add a focus request on every tap on the TextFormField.
1. Create a FocusNode property
class CustomTextFormFieldState extends State<CustomTextFormField> {
FocusNode _focusNode;
...
2. Add initialization and disposal to it
#override
void initState() {
super.initState();
_focusNode = FocusNode();
}
#override
void dispose() {
_focusNode.dispose();
super.dispose();
}
3. Add it to the TextFormField
#override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
...
4. Add a focus request on every tap on the TextFormField
Don't forget to use setState:
void _requestFocus(){
setState(() {
FocusScope.of(context).requestFocus(_focusNode);
});
}
Add the method to the TextFormField's onTap property:
#override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
onTap: _requestFocus,
...
Use themes, this would only have to be done once in a central place:
inputDecorationTheme: InputDecorationTheme(
floatingLabelStyle: TextStyle(color: Colors.blue),
),
A quick solution is changing the primarySwatch from the theme of the Widget MaterialApp. The only disadvantage is that a Material Color is required.
I solve this problem with a Focus widget. First I defined a Color-Variable for each Field:
final _lowColor = Colors.amber[50]; // use your own colors
final _highColor = Colors.amber[200];
Color _field1Color = _lowColor;
Color _field2Color = _lowColor;
...
Then I wrapped each TextFormField with a Focus Widget and change the fieldColor:
child: Focus(
onFocusChange: (hasFocus) {
setState(() => _field1Color = hasFocus ? _highColor : _lowColor);
},
child: TextFormField(
...
color: _field1Color,
...
),
),
),
Here is a quick method without using stateful widget
return Theme( // 1) wrap with theme widget
data: Theme.of(context).copyWith(primaryColor: //2) color you want here)
child: TextFormField(
focusNode: myFocusNode,
decoration: InputDecoration(
labelText: 'test',
),
),
);
https://api.flutter.dev/flutter/material/InputDecoration/labelStyle.html
labelStyle: MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final Color color = states.contains(MaterialState.focused)
? Colors.pink
: Colors.orange;
return TextStyle(color: color);
}),
for active/click
floatingLabelStyle: TextStyle(color: Colors.yellow),
for inactive
labelStyle: TextStyle(color: Colors.black),
below is complete example
TextField(
decoration: InputDecoration(
hintText: 'Verify Password',
focusColor: appColor,
labelText: "Verify Password",
labelStyle: TextStyle(color: Colors.black),
floatingLabelStyle: TextStyle(color: appColor),
floatingLabelBehavior: FloatingLabelBehavior.always
),
cursorColor: appColor,
)
Update
As mentioned by Guilherme in the comment, the later version of Flutter uses different logic to get the color
Color _getActiveColor(ThemeData themeData) {
if (isFocused) {
return themeData.colorScheme.primary;
}
return themeData.hintColor;
}
Source
You will now need to set it from the colorScheme instead
ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: activeColor,
),
)
Original answer
After digging the source code for the InputDecorator used to determine the label color, here's what I found.
TextStyle _getFloatingLabelStyle(ThemeData themeData) {
final Color color = decoration.errorText != null
? decoration.errorStyle?.color ?? themeData.errorColor
: _getActiveColor(themeData);
final TextStyle style = themeData.textTheme.subtitle1.merge(widget.baseStyle);
return style
.copyWith(color: decoration.enabled ? color : themeData.disabledColor)
.merge(decoration.labelStyle);
}
Color _getActiveColor(ThemeData themeData) {
if (isFocused) {
switch (themeData.brightness) {
case Brightness.dark:
return themeData.accentColor;
case Brightness.light:
return themeData.primaryColor;
}
}
return themeData.hintColor;
}
In short, to change the label color, set the primaryColor light theme or accentColor for dark theme.
Another tip: To change the label color while it's not focused, set hintColor.
ThemeData.dark().copyWith(
primaryColor: Colors.red,
accentColor: Colors.white,
hintColor: Colors.pink,
)
One more clean way to do it with styles (you can add styles to the main theme and use for dark \ light modes)
TextFormField(
decoration: InputDecoration(
labelText: "some label",
labelStyle: const TextStyle(color: Colors.grey),
floatingLabelStyle: const TextStyle(color: Colors.blueAccent),
),),
you can also use labelStyle when the text field is in focus and if the text field is erroneous (caused by not following the validation)
labelText: 'Password',
labelStyle: TextStyle(
color: Colors.black54,
),
//when error has occured
errorStyle: TextStyle(
color: Colors.black,
),
I solved the problem using a StatefulWidget and Focus widget.
I use StatefulWidget because you need to use setState to notify the color change when focus on input
class InputEmail extends StatefulWidget {
#override
_InputEmailState createState() => _InputEmailState();
}
class _InputEmailState extends State<InputEmail> {
Color _colorText = Colors.black54;
#override
Widget build(BuildContext context) {
const _defaultColor = Colors.black54;
const _focusColor = Colors.purple;
return Container(
padding: EdgeInsets.symmetric(vertical: 15),
child: Focus(
onFocusChange: (hasFocus) {
// When you focus on input email, you need to notify the color change into the widget.
setState(() => _colorText = hasFocus ? _focusColor : _defaultColor);
},
child: TextField(
// Validate input Email
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'example#domain.com',
labelText: 'Email',
labelStyle: TextStyle(color: _colorText),
// Default Color underline
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black26),
),
// Focus Color underline
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.purple),
),
icon: Icon(
Icons.mail,
color: Colors.deepPurpleAccent,
),
),
),
),
);
}
}
If You want to change the primary color. Just simply define add the primaryColor of the Widget MaterialApp
const appPrimaryColor = Color(0xFF746DF7);
ThemeData theme() {
return ThemeData(
scaffoldBackgroundColor: Colors.white,
fontFamily: "Inter",
appBarTheme: appBarTheme(),
textTheme: textTheme(),
inputDecorationTheme: inputDecorationTheme(),
visualDensity: VisualDensity.adaptivePlatformDensity,
primaryColor: appPrimaryColor // <------ HERE
);
}
MaterialApp(
title: 'Flutter Demo',
theme: theme(), // <------ HERE
home: SplashScreen(),
routes: routes,
)
You can wrap the textfield with Theme and set the primary color to whatever you want the label color to be
There is a 'lableStyle' in 'decoration', just like:
labelText: 'Description',
labelStyle: TextStyle(
color: Colors.lightBlueAccent,
)),
There is a floatingLabelStyle parameter in the InputDecoration, you can use it like this:
decoration: InputDecoration(
labelText: "label",
hintText: "hint",
labelStyle: GoogleFonts.roboto(
color: color.labelColor,
),
floatingLabelStyle: GoogleFonts.roboto(
color: color.defaultGreen,
),),