(Flutter)TextFormField 在焦点上更改 labelColor
(Flutter) TextFormField Change labelColor on Focus
我正在尝试更改 labelText
聚焦时的颜色。我可以更改文本颜色,但在聚焦时不能。
我已经尝试了所有的提示文字颜色和标签文字颜色,但没有任何帮助。
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()
),
)
),
),
以下是正在发生的事情的图像:
您需要有一种方法来确定其焦点状态,然后根据该状态为其颜色创建条件。这是 focusNode
会有所帮助的地方。从小部件创建中构建一个新的 FocusNode
,将其用作 TextFormField
中的 focusNode
属性。然后在颜色 属性 of the TextStyle
属性 of the TextFormField
你可以添加这样的东西:
FocusNode myFocusNode = new FocusNode();
...
return TextFormField(
focusNode: myFocusNode,
decoration: InputDecoration(
labelText: 'test',
labelStyle: TextStyle(
color: myFocusNode.hasFocus ? Colors.blue : Colors.black
)
),
);
编辑:快速说明一下,您可能需要确保它在 StatefulWidget
中,然后将侦听器添加到您创建的 focusNode
并调用 setState
focusNode
上的任何事件。否则你将看不到任何变化。
总结
您可能想查看 Flutter Cookbook's Focus and text fields 食谱。
本质上,我们必须:
- 创建
FocusNode
属性。
- 为其添加初始化和处置。
- 将其添加到
TextFormField
。
- 每次点击
TextFormField
添加焦点请求。
1。创建 FocusNode
属性
class CustomTextFormFieldState extends State<CustomTextFormField> {
FocusNode _focusNode;
...
2。为其添加初始化和处置
@override
void initState() {
super.initState();
_focusNode = FocusNode();
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
3。将其添加到 TextFormField
@override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
...
4。在 TextFormField
上的每次点击添加焦点请求
别忘了使用setState
:
void _requestFocus(){
setState(() {
FocusScope.of(context).requestFocus(_focusNode);
});
}
将方法添加到 TextFormField
的 onTap
属性:
@override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
onTap: _requestFocus,
...
一个快速的解决方案是将小部件 MaterialApp
的 theme
更改为 primarySwatch
。唯一的缺点是需要Material Color
。
更新
如评论中Guilherme所述,Flutter后期版本使用不同的逻辑获取颜色
Color _getActiveColor(ThemeData themeData) {
if (isFocused) {
return themeData.colorScheme.primary;
}
return themeData.hintColor;
}
您现在需要从 colorScheme
改为
进行设置
ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: activeColor,
),
)
原回答
在挖掘用于确定标签颜色的 InputDecorator
的源代码后,这是我发现的。
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;
}
简而言之,要更改标签颜色,请设置 primaryColor
浅色主题或 accentColor
深色主题。
另一个提示:要在未聚焦时更改标签颜色,请设置 hintColor
。
ThemeData.dark().copyWith(
primaryColor: Colors.red,
accentColor: Colors.white,
hintColor: Colors.pink,
)
当文本字段处于焦点状态并且文本字段有误(未遵循验证导致)时,您也可以使用 labelStyle
labelText: 'Password',
labelStyle: TextStyle(
color: Colors.black54,
),
//when error has occured
errorStyle: TextStyle(
color: Colors.black,
),
您可以用 Theme
包装文本字段,并将主要颜色设置为您想要的标签颜色
这是一种不使用有状态小部件的快速方法
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',
),
),
);
'decoration'中有一个'lableStyle',就像:
labelText: 'Description',
labelStyle: TextStyle(
color: Colors.lightBlueAccent,
)),
我用焦点小部件解决了这个问题。首先,我为每个字段定义了一个颜色变量:
final _lowColor = Colors.amber[50]; // use your own colors
final _highColor = Colors.amber[200];
Color _field1Color = _lowColor;
Color _field2Color = _lowColor;
...
然后我用一个 Focus Widget 包装了每个 TextFormField 并更改了 fieldColor:
child: Focus(
onFocusChange: (hasFocus) {
setState(() => _field1Color = hasFocus ? _highColor : _lowColor);
},
child: TextFormField(
...
color: _field1Color,
...
),
),
),
如果您想更改原色。只需简单地定义添加 Widget MaterialApp
的 primaryColor
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,
)
我使用 StatefulWidget
和 Focus
小部件解决了这个问题。
我使用 StatefulWidget 是因为你需要使用 setState 来通知焦点输入时的颜色变化
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,
),
),
),
),
);
}
}
使用主题:
inputDecorationTheme: InputDecorationTheme(
floatingLabelStyle: TextStyle(color: Colors.blue),
),
InputDecoration中有一个floatingLabelStyle参数,你可以这样使用:
decoration: InputDecoration(
labelText: "label",
hintText: "hint",
labelStyle: GoogleFonts.roboto(
color: color.labelColor,
),
floatingLabelStyle: GoogleFonts.roboto(
color: color.defaultGreen,
),),
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);
}),
一种使用样式的更简洁的方法(您可以将样式添加到主题并用于暗\亮模式)
TextFormField(
decoration: InputDecoration(
labelText: "some label",
labelStyle: const TextStyle(color: Colors.grey),
floatingLabelStyle: const TextStyle(color: Colors.blueAccent),
),),
我正在尝试更改 labelText
聚焦时的颜色。我可以更改文本颜色,但在聚焦时不能。
我已经尝试了所有的提示文字颜色和标签文字颜色,但没有任何帮助。
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()
),
)
),
),
以下是正在发生的事情的图像:
您需要有一种方法来确定其焦点状态,然后根据该状态为其颜色创建条件。这是 focusNode
会有所帮助的地方。从小部件创建中构建一个新的 FocusNode
,将其用作 TextFormField
中的 focusNode
属性。然后在颜色 属性 of the TextStyle
属性 of the TextFormField
你可以添加这样的东西:
FocusNode myFocusNode = new FocusNode();
...
return TextFormField(
focusNode: myFocusNode,
decoration: InputDecoration(
labelText: 'test',
labelStyle: TextStyle(
color: myFocusNode.hasFocus ? Colors.blue : Colors.black
)
),
);
编辑:快速说明一下,您可能需要确保它在 StatefulWidget
中,然后将侦听器添加到您创建的 focusNode
并调用 setState
focusNode
上的任何事件。否则你将看不到任何变化。
总结
您可能想查看 Flutter Cookbook's Focus and text fields 食谱。
本质上,我们必须:
- 创建
FocusNode
属性。 - 为其添加初始化和处置。
- 将其添加到
TextFormField
。 - 每次点击
TextFormField
添加焦点请求。
1。创建 FocusNode
属性
class CustomTextFormFieldState extends State<CustomTextFormField> {
FocusNode _focusNode;
...
2。为其添加初始化和处置
@override
void initState() {
super.initState();
_focusNode = FocusNode();
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
3。将其添加到 TextFormField
@override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
...
4。在 TextFormField
上的每次点击添加焦点请求
别忘了使用setState
:
void _requestFocus(){
setState(() {
FocusScope.of(context).requestFocus(_focusNode);
});
}
将方法添加到 TextFormField
的 onTap
属性:
@override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
onTap: _requestFocus,
...
一个快速的解决方案是将小部件 MaterialApp
的 theme
更改为 primarySwatch
。唯一的缺点是需要Material Color
。
更新
如评论中Guilherme所述,Flutter后期版本使用不同的逻辑获取颜色
Color _getActiveColor(ThemeData themeData) {
if (isFocused) {
return themeData.colorScheme.primary;
}
return themeData.hintColor;
}
您现在需要从 colorScheme
改为
ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: activeColor,
),
)
原回答
在挖掘用于确定标签颜色的 InputDecorator
的源代码后,这是我发现的。
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;
}
简而言之,要更改标签颜色,请设置 primaryColor
浅色主题或 accentColor
深色主题。
另一个提示:要在未聚焦时更改标签颜色,请设置 hintColor
。
ThemeData.dark().copyWith(
primaryColor: Colors.red,
accentColor: Colors.white,
hintColor: Colors.pink,
)
当文本字段处于焦点状态并且文本字段有误(未遵循验证导致)时,您也可以使用 labelStyle
labelText: 'Password',
labelStyle: TextStyle(
color: Colors.black54,
),
//when error has occured
errorStyle: TextStyle(
color: Colors.black,
),
您可以用 Theme
包装文本字段,并将主要颜色设置为您想要的标签颜色
这是一种不使用有状态小部件的快速方法
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',
),
),
);
'decoration'中有一个'lableStyle',就像:
labelText: 'Description',
labelStyle: TextStyle(
color: Colors.lightBlueAccent,
)),
我用焦点小部件解决了这个问题。首先,我为每个字段定义了一个颜色变量:
final _lowColor = Colors.amber[50]; // use your own colors
final _highColor = Colors.amber[200];
Color _field1Color = _lowColor;
Color _field2Color = _lowColor;
...
然后我用一个 Focus Widget 包装了每个 TextFormField 并更改了 fieldColor:
child: Focus(
onFocusChange: (hasFocus) {
setState(() => _field1Color = hasFocus ? _highColor : _lowColor);
},
child: TextFormField(
...
color: _field1Color,
...
),
),
),
如果您想更改原色。只需简单地定义添加 Widget MaterialApp
的primaryColor
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,
)
我使用 StatefulWidget
和 Focus
小部件解决了这个问题。
我使用 StatefulWidget 是因为你需要使用 setState 来通知焦点输入时的颜色变化
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,
),
),
),
),
);
}
}
使用主题:
inputDecorationTheme: InputDecorationTheme(
floatingLabelStyle: TextStyle(color: Colors.blue),
),
InputDecoration中有一个floatingLabelStyle参数,你可以这样使用:
decoration: InputDecoration(
labelText: "label",
hintText: "hint",
labelStyle: GoogleFonts.roboto(
color: color.labelColor,
),
floatingLabelStyle: GoogleFonts.roboto(
color: color.defaultGreen,
),),
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);
}),
一种使用样式的更简洁的方法(您可以将样式添加到主题并用于暗\亮模式)
TextFormField(
decoration: InputDecoration(
labelText: "some label",
labelStyle: const TextStyle(color: Colors.grey),
floatingLabelStyle: const TextStyle(color: Colors.blueAccent),
),),