setState 不会重新渲染 textformfield
setState doesn't rerender textformfield
我正在尝试将 PasswordField 创建为 TextFormField,它有一个后缀,应该允许切换输入字符串的可见性。我收到的问题是,我能够在 true 和 false 之间切换 obscureText,但不会发生重新渲染。我希望有人可以帮助我解决这个问题。我将在下面添加代码
class _WFPasswordInputState extends State<WFPasswordInput> {
TextEditingController? controller;
TextFormField? formField;
late bool obscureText;
late FocusNode _focusNode;
final AppTheme style = AppTheme();
@override
void initState() {
_focusNode = FocusNode();
obscureText = widget.obscureText;
super.initState();
}
@override
void dispose() {
_focusNode.dispose();
formField!.controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
String formatted = widget.value.value?.toString() ?? '';
if (formField == null) {
TextEditingController controller;
if (widget.controller == null) {
controller = TextEditingController(text: formatted);
} else {
controller = widget.controller!;
}
formField = createTextFormField();
} else {
Future.delayed(
Duration.zero,
() {
if (formField!.controller?.text !=
(widget.value.display == null
? null
: widget.value.value.toString())) {
String formatted = widget.value.value!;
if (formField!.controller!.text.isEmpty) {
formatted = "";
}
formField!.controller?.text = formatted;
formField!.controller?.selection = TextSelection(
baseOffset: formatted.length,
extentOffset: formatted.length,
);
}
},
);
}
return formField!;
}
TextFormField createTextFormField() {
return TextFormField(
enabled: widget.enabled,
controller: controller,
keyboardType: widget.inputType,
focusNode: widget.focusNode,
obscureText: obscureText,
textAlign: widget.textAlignment,
inputFormatters: widget.inputFormatters,
maxLines:
widget.inputType == TextInputType.multiline ? widget.maxLines : 1,
minLines: widget.minLines,
style: widget.textStyle ??
style.textStyles.bodyText1!
.copyWith(color: Colors.white.withOpacity(0.5)),
decoration: CustomInputDecoration(
hintStyle: AppTheme()
.textStyles
.bodyText1!
.copyWith(color: Colors.white.withOpacity(0.5)),
hintText: widget.hintText,
suffix: passwordIcons(),
contentPadding: style.px4y2),
onChanged: (value) {
widget.value.value = value;
},
validator: widget.validator,
);
}
Widget passwordIcons() {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () {
setState(() {
obscureText = !obscureText;
print(obscureText);
});
},
icon: Icon(
obscureText ? Icons.visibility : Icons.visibility_off,
color: style.white.withOpacity(0.5),
),
color: style.white,
),
IconButton(
onPressed: showPasswordAlert,
icon: const Icon(Icons.info_outline),
color: style.white,
),
],
);
}
}
所以这基本上应该如何工作是我打电话
obscureText = widget.obscureText;
在 initState 方法中。每次我单击 passwordIcons
小部件中的 IconButton 时,都应调用 setState 并根据 obscureText 值重新呈现它。但是我就是没看到错误。
提前致谢。
您的方法的问题在于您使用以下代码仅创建了一次 formField
:
if (formField == null) {
...
formField = createTextFormField();
}
您是在强制框架不重建此小部件,但使用 setState
的全部意义在于重建。
这样 Flutter 框架将不会在调用 setState
时更新此小部件。相反,直接将此小部件添加到您的小部件树中,setState
将起作用。而不是这个:
return formField!;
试试这个:
return TextFormField(
enabled: widget.enabled,
controller: controller,
keyboardType: widget.inputType,
focusNode: widget.focusNode,
obscureText: obscureText,
...
我正在尝试将 PasswordField 创建为 TextFormField,它有一个后缀,应该允许切换输入字符串的可见性。我收到的问题是,我能够在 true 和 false 之间切换 obscureText,但不会发生重新渲染。我希望有人可以帮助我解决这个问题。我将在下面添加代码
class _WFPasswordInputState extends State<WFPasswordInput> {
TextEditingController? controller;
TextFormField? formField;
late bool obscureText;
late FocusNode _focusNode;
final AppTheme style = AppTheme();
@override
void initState() {
_focusNode = FocusNode();
obscureText = widget.obscureText;
super.initState();
}
@override
void dispose() {
_focusNode.dispose();
formField!.controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
String formatted = widget.value.value?.toString() ?? '';
if (formField == null) {
TextEditingController controller;
if (widget.controller == null) {
controller = TextEditingController(text: formatted);
} else {
controller = widget.controller!;
}
formField = createTextFormField();
} else {
Future.delayed(
Duration.zero,
() {
if (formField!.controller?.text !=
(widget.value.display == null
? null
: widget.value.value.toString())) {
String formatted = widget.value.value!;
if (formField!.controller!.text.isEmpty) {
formatted = "";
}
formField!.controller?.text = formatted;
formField!.controller?.selection = TextSelection(
baseOffset: formatted.length,
extentOffset: formatted.length,
);
}
},
);
}
return formField!;
}
TextFormField createTextFormField() {
return TextFormField(
enabled: widget.enabled,
controller: controller,
keyboardType: widget.inputType,
focusNode: widget.focusNode,
obscureText: obscureText,
textAlign: widget.textAlignment,
inputFormatters: widget.inputFormatters,
maxLines:
widget.inputType == TextInputType.multiline ? widget.maxLines : 1,
minLines: widget.minLines,
style: widget.textStyle ??
style.textStyles.bodyText1!
.copyWith(color: Colors.white.withOpacity(0.5)),
decoration: CustomInputDecoration(
hintStyle: AppTheme()
.textStyles
.bodyText1!
.copyWith(color: Colors.white.withOpacity(0.5)),
hintText: widget.hintText,
suffix: passwordIcons(),
contentPadding: style.px4y2),
onChanged: (value) {
widget.value.value = value;
},
validator: widget.validator,
);
}
Widget passwordIcons() {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () {
setState(() {
obscureText = !obscureText;
print(obscureText);
});
},
icon: Icon(
obscureText ? Icons.visibility : Icons.visibility_off,
color: style.white.withOpacity(0.5),
),
color: style.white,
),
IconButton(
onPressed: showPasswordAlert,
icon: const Icon(Icons.info_outline),
color: style.white,
),
],
);
}
}
所以这基本上应该如何工作是我打电话
obscureText = widget.obscureText;
在 initState 方法中。每次我单击 passwordIcons
小部件中的 IconButton 时,都应调用 setState 并根据 obscureText 值重新呈现它。但是我就是没看到错误。
提前致谢。
您的方法的问题在于您使用以下代码仅创建了一次 formField
:
if (formField == null) {
...
formField = createTextFormField();
}
您是在强制框架不重建此小部件,但使用 setState
的全部意义在于重建。
这样 Flutter 框架将不会在调用 setState
时更新此小部件。相反,直接将此小部件添加到您的小部件树中,setState
将起作用。而不是这个:
return formField!;
试试这个:
return TextFormField(
enabled: widget.enabled,
controller: controller,
keyboardType: widget.inputType,
focusNode: widget.focusNode,
obscureText: obscureText,
...