如何在 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;
}
});
});
}
我正在尝试创建一个从密码 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;
}
});
});
}