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,
  ...