我无法测试您的代码,但我有一个自定义文本字段小部件,它允许使用属性来定义是普通文本字段还是密码文本字段,也许这对您有帮助
class DnetTextField extends StatefulWidget {
final String label;
final bool isPasswordField;
final TextEditingController controller;
final TextInputType textInputType;
final TextInputAction textInputAction;
final FormFieldValidator validator;
final IconData icon;
final Color color;
final Color errorColor;
final BuildContext context;
final FocusNode currentFocus;
final FocusNode nextFocus;
final bool autoValidate;
final double width;
final ValueChanged<String> onFieldSubmitted;
final List<TextInputFormatter> inputFormatters;
final TextCapitalization textCapitalization;
final int maxLength;
final bool focusable;
final String hint;
DnetTextField({
@required this.context,
@required this.label,
@required this.controller,
this.icon,
this.color,
this.errorColor,
this.textInputType = TextInputType.text,
this.textInputAction = TextInputAction.done,
this.validator,
this.isPasswordField = false,
this.currentFocus,
this.nextFocus,
this.onFieldSubmitted,
this.autoValidate = false,
this.width = 266,
this.inputFormatters,
this.textCapitalization = TextCapitalization.none,
this.maxLength = -1,
this.focusable = true,
this.hint,
});
@override
DnetTextFieldState createState() {
return DnetTextFieldState();
}
}
class DnetTextFieldState extends State<DnetTextField> {
bool hasErrors = false;
bool passwordVisible = false;
Color get currentColor => hasErrors ? widget.errorColor : widget.color;
IconData get currentIcon {
if (widget.isPasswordField) if (passwordVisible)
return Icons.visibility_off;
else
return Icons.visibility;
else
return widget.icon;
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
final border = OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: currentColor),
);
final focusableTheme = widget.focusable
? Theme.of(context)
: Theme.of(
context,
).copyWith(
splashFactory: const NoSplashFactory(),
);
return Container(
width: widget.width,
height: 80,
child: Theme(
data: focusableTheme,
child: TextFormField(
inputFormatters: widget.inputFormatters,
style: TextStyle(color: currentColor),
controller: widget.controller,
keyboardType: widget.textInputType,
textInputAction: widget.textInputAction,
enableInteractiveSelection: widget.focusable,
focusNode:
widget.focusable ? widget.currentFocus : DnetDisabledFocusNode(),
decoration: InputDecoration(
hintText: widget.hint,
suffixIcon: getSuffixIcon(),
fillColor: currentColor,
labelText: widget.label,
labelStyle:
TextStyle(color: currentColor, fontStyle: FontStyle.italic),
focusedBorder: border,
enabledBorder: border,
border: border,
),
autovalidate: widget.autoValidate,
validator: (text) {
final validatorMessage =
widget.validator == null ? null : widget.validator(text);
setHasErrors(validatorMessage != null);
if (validatorMessage != null) return validatorMessage;
},
onFieldSubmitted: widget.onFieldSubmitted ??
(term) {
if (widget.nextFocus != null) {
FocusScope.of(context).requestFocus(widget.nextFocus);
}
},
obscureText: widget.isPasswordField && !passwordVisible,
textCapitalization: widget.textCapitalization,
maxLength: widget.maxLength != -1 ? widget.maxLength : null,
),
),
);
}
setHasErrors(bool errors) {
setState(() {
hasErrors = errors;
});
}
setPasswordVisible(bool visible) {
setState(() {
passwordVisible = visible;
});
}
GestureDetector getSuffixIcon() {
if (widget.icon != null || widget.isPasswordField) {
return GestureDetector(
child: Icon(
currentIcon,
color: currentColor,
),
onTap: () {
if (widget.isPasswordField) setPasswordVisible(!passwordVisible);
},
);
} else {
return null;
}
}
}