如何在 Flutter 中制作密码验证动画

How to do a password validation animation in Flutter

我正在尝试创建一个从密码 TextFormField() 中获取值的函数,并检查用户是否在其中包含大写字母、小写字母、数字和特殊字符,并据此进行更新我拥有的 Text('Must have an upperCase letter') 个小部件,并相应地更改它们的颜色和图标。

使用我的代码,我不断收到此错误:

setState() or markNeedsBuild called during build

我正在尝试做的一个工作示例是 here

到目前为止我的函数(也是我的验证器):

String isPasswordCompliant(String password, [int minLength = 6]) {
      if (password.length < minLength || password.isEmpty) {
        return 'Password must be at least 6 characters long';
      }
      if (password.contains(RegExp(r"[a-z]"))) {
        setState(() {
          _passwordChecker.hasLowercase = true;
        });
      }
      if (password.contains(RegExp(r"[A-Z]"))) {
        setState(() {
          _passwordChecker.hasUppercase = true;
        });
      }
      if (password.contains(RegExp(r"[0-9]"))) {
        setState(() {
          _passwordChecker.hasDigits = true;
        });
      }
      if (password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'))) {
        setState(() {
          _passwordChecker.hasSpecialCharacters = true;
        });
      } else {
        return null;
      }
  }

我是如何实现这个功能的:

                    TextFormField(
                      decoration: const InputDecoration(labelText: 'Password'),
                      obscureText: true,
                      controller: _passwordController,
                      textInputAction: TextInputAction.next,
                      onFieldSubmitted: (_) {
                        FocusScope.of(context)
                            .requestFocus(_confirmPasswordFocusNode);
                      },
                      focusNode: _passwordFocusNode,
                      validator: (value) => isPasswordCompliant(value),
                      onSaved: (value) {
                        _authData['password'] = value;
                      },
                    ),

我的 Text() 小部件:

class PasswordChecker extends StatelessWidget {
  PasswordChecker(this._passwordChecker);
  final PasswordValidationModel _passwordChecker;
  // final _passwordChecker = PasswordValidationModel();
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        TextButton.icon(
          icon: _passwordChecker.hasUppercase == true
              ? Icon(Icons.done)
              : Icon(Icons.clear),
          label: Text(
            'Must have at least one upperCase letter',
          ),
          onPressed: () {},
        ),
        TextButton.icon(
          icon: _passwordChecker.hasLowercase == true
              ? Icon(Icons.done)
              : Icon(Icons.clear),
          label: Text(
            'Must have at least one lowerCase letter',
          ),
          onPressed: () {},
        ),
        TextButton.icon(
          icon: _passwordChecker.hasDigits == true
              ? Icon(Icons.done)
              : Icon(Icons.clear),
          label: Text(
            'Must have at least one number',
          ),
          onPressed: () {},
        ),
        TextButton.icon(
          icon: _passwordChecker.hasSpecialCharacters == true
              ? Icon(Icons.done)
              : Icon(Icons.clear),
          label: Text(
            'Must have at least one special character',
          ),
          onPressed: () {},
        ),
      ],
    );
  }
}

在我做了更多研究之后,我发现了一个类似的 project 并提出了一个简单的解决方案,通过向密码控制器添加一个 addListener() 并在 initState() 中初始化它并且在那里做逻辑。

@override
  void initState() {
    super.initState();
    _passwordController.addListener(() {
      setState(() {
        if (_passwordChecker.hasLowercase =
            _passwordController.text.contains(RegExp(r'[a-z]'))) {
          _passwordChecker.hasLowercase = true;
        }
        if (_passwordChecker.hasUppercase =
            _passwordController.text.contains(RegExp(r'[A-Z]'))) {
          _passwordChecker.hasUppercase = true;
        }
        if (_passwordChecker.hasDigits =
            _passwordController.text.contains(RegExp(r'[0-9]'))) {
          _passwordChecker.hasDigits = true;
        }
        if (_passwordChecker.hasSpecialCharacters = _passwordController.text
            .contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'))) {
          _passwordChecker.hasSpecialCharacters = true;
        }
      });
    });
  }