很遗憾,我不知道如何使用默认工具完成它,但我用另一种方法来完成它,也许对你有帮助。
FocusNode
和边框颜色的变量:// Use it to change color for border when textFiled in focus
FocusNode _focusNode = FocusNode();
// Color for border
Color _borderColor = Colors.grey;
initState
内为textField
创建监听器,如果textField
处于焦点状态,将边框颜色更改为橙色,否则更改为灰色:@override
void initState() {
super.initState();
// Change color for border if focus was changed
_focusNode.addListener(() {
setState(() {
_borderColor = _focusNode.hasFocus ? Colors.orange : Colors.grey;
});
});
}
textField
创建带有边框的 Container
,添加 focusNode
并设置装饰到 textField
:Container(
decoration: BoxDecoration(
border: Border.all(color: _borderColor),
borderRadius: BorderRadius.circular(4),
),
child: TextField(
focusNode: _focusNode,
style: TextStyle(color: Colors.grey),
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
labelText: "Amount",
prefixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0),
prefixIcon: Padding(
padding: EdgeInsets.symmetric(vertical: 18, horizontal: 8),
child: Text("₦", style: TextStyle(fontSize: 16, color: Colors.grey)),
),
),
),
),
focusNode
调用dispose
:@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
class TextFieldDesignPage extends StatefulWidget {
TextFieldDesignPage({Key? key}) : super(key: key);
@override
_TextFieldDesignPageState createState() => _TextFieldDesignPageState();
}
class _TextFieldDesignPageState extends State<TextFieldDesignPage> {
// Use it to change color for border when textFiled in focus
FocusNode _focusNode = FocusNode();
// Color for border
Color _borderColor = Colors.grey;
@override
void initState() {
super.initState();
// Change color for border if focus was changed
_focusNode.addListener(() {
setState(() {
_borderColor = _focusNode.hasFocus ? Colors.orange : Colors.grey;
});
});
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(color: _borderColor),
borderRadius: BorderRadius.circular(4),
),
child: TextField(
focusNode: _focusNode,
style: TextStyle(color: Colors.grey),
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
labelText: "Amount",
prefixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0),
prefixIcon: Padding(
padding: EdgeInsets.symmetric(vertical: 18, horizontal: 8),
child: Text("₦", style: TextStyle(fontSize: 16, color: Colors.grey)),
),
),
),
),
),
);
}
}
结果:
TextField
使用边框,我使用了包含TextField
的Container
的边框。我检查过了,使用TextFormField
也可以正确工作。为了证明这一点,在示例代码中将TextField
更改为TextFormField
即可。 - Andrei RTextFiled
的onChange
参数中实现验证,并根据验证结果更改颜色。
以下是一个小例子:
onChanged: (String text) { setState(() { _borderColor = text.length > 4 ? Colors.orange : Colors.red; }); },
此外,你还可以使用TextEditingController
进行高级控制。
如果你有问题,请提出具体的例子。 - Andrei Rclass MyInputTextField extends StatefulWidget {
final String? title;
final String? helperText;
final bool isSecure;
final int maxLength;
final String? hint;
final TextInputType? inputType;
final String? initValue;
final Color? backColor;
final Widget? suffix;
final Widget? prefix;
final TextEditingController? textEditingController;
final String? Function(String? value)? validator;
final Function(String)? onTextChanged;
final Function(String)? onSaved;
List<TextInputFormatter>? inputFormatters;
static const int MAX_LENGTH = 500;
MyInputTextField({
this.title,
this.hint,
this.helperText,
this.inputType,
this.initValue = "",
this.isSecure = false,
this.textEditingController,
this.validator,
this.maxLength = MAX_LENGTH,
this.onTextChanged,
this.onSaved,
this.inputFormatters,
this.backColor,
this.suffix,
this.prefix,
});
@override
_MyInputTextFieldState createState() => _MyInputTextFieldState();
}
class _MyInputTextFieldState extends State<MyInputTextField> {
late bool _passwordVisibility;
late ThemeData theme;
FocusNode _focusNode = FocusNode();
Color _borderColor = getColors().primaryVariant;
double _borderSize = 1;
@override
void initState() {
super.initState();
_passwordVisibility = !widget.isSecure;
widget.textEditingController?.text = widget.initValue ?? "";
_focusNode.addListener(() {
setState(() {
_borderSize = _focusNode.hasFocus ? 1.7 : 1;
});
});
}
@override
void didChangeDependencies() {
theme = Theme.of(context);
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: 55,
decoration: BoxDecoration(
border: Border.all(color: _borderColor, width: _borderSize),
borderRadius: BorderRadius.circular(AppDimens.radiusSmall),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: TextFormField(
focusNode: _focusNode,
controller: widget.textEditingController,
autocorrect: false,
obscureText: !_passwordVisibility,
keyboardType: widget.inputType,
cursorColor: Colors.white,
validator: (value) {
String? f = widget.validator?.call(value);
setState(() {
_borderColor = f != null ? getColors().redError : getColors().primaryVariant;
});
return f;
},
style: theme.textTheme.bodyText1,
maxLength: widget.maxLength,
inputFormatters: widget.inputFormatters,
maxLines: 1,
onChanged: (text) {
widget.onTextChanged?.call(text);
},
decoration: InputDecoration(
counterText: "",
hintStyle: theme.textTheme.subtitle1,
floatingLabelStyle: theme.textTheme.headline6?.copyWith(color: getColors().textSubtitle),
labelText: widget.title,
helperText: widget.helperText,
suffixIcon: getSuffixIcon(),
prefixIcon: widget.prefix,
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
),
),
)
],
);
}
Widget? getSuffixIcon() {
return widget.isSecure ? getPasswordSuffixIcon() : widget.suffix;
}
Widget? getPasswordSuffixIcon() {
return IconButton(
hoverColor: Colors.transparent,
focusColor: Colors.transparent,
splashColor: Colors.transparent,
padding: EdgeInsets.zero,
icon: _passwordVisibility ? Icon(AppIcons.password_eye) : Icon(AppIcons.password_eye_blind),
color: Colors.white,
onPressed: () {
setState(() {
_passwordVisibility = !_passwordVisibility;
});
},
);
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
}