前语
咱们经常在一些网站上看到这样的暗码强度指示,运用三段线,别离用不同的色彩来表示弱暗码、中等强度暗码和强暗码。这种办法能够让用户清晰地感知到自己设置暗码的强度,体验上更为友好。本篇咱们就用 Flutter 来完结这样一个暗码强度校验示例。最终完结的作用如下图。
组件剖析
这儿面实践上是暗码强度要动态随暗码输入框的内容改变,因而需求监听输入框内容的改变。惯例的做法是在输入框的 onChanged
办法里 setState
来更新整个组件。但是,实践上有更优雅的完结办法,那便是运用 Dart 的Stream
来完结部分改写,也便是输入内容改变时只改写暗码强度指示区域。稍后咱们会讲具体的完结。
界面上,实践上组件的层级联系如下图所示。
为了简化嵌套层级,咱们将框起来的部分,也便是暗码强度指示单独封装成一个组件,叫做PasswordStrengthIndicator
。这个组件也便是需求跟随文本输入框内容改变而部分改写的组件。这儿顺带说一下,如果要考虑部分改写,那么就需求合理的封装组件,将需求部分改写的组件和不需求改写的部分拆分开,这样就能够在最小规模操控要改写的组件。
最终是暗码强度校验的逻辑,咱们的逻辑如下:
- 暗码长度低于8或者只包括数字、字母和特别字符中的一个,则认为是弱暗码;
- 暗码长度大于8,且只包括数字、字母和特别字符中的两个,则认为是中等强度暗码;
- 暗码长度大于8,且一起包括数字、字母和特别字符,则认为是强暗码。
这个逻辑能够经过正则匹配来完结。
最终是暗码强度指示组件的完结,咱们要保证三段线等宽且等份额,那么就能够用一个 Flex
组件包裹一个 Container
组件,设置份额 flex
值为1,就能够了。这样做法的好处是不需求写死 Container
的宽度,适用性更强。
代码完结
咱们先来看一下 Stream
如何完结部分改写。在 Flutter 里,供给了一个 基于 Stream
构建组件的 StreamBuilder
类。当StreamBuilder
监听到 Stream
内容发生改变时,就会调用其builder
办法从头构建一个组件并返回。StreamBuilder
的界说如下:
const StreamBuilder({
super.key,
this.initialData,
super.stream,
required this.builder,
});
这是一个泛型类,因而能够接收任何类型的数据,比如咱们自界说的事务目标。其中各个参数阐明如下:
-
initialData
是初始值; -
stream
即要监听的数据流,一般由一个StreamController
供给(也能够是网络数据流)。 -
builder
即组件构建办法,该办法会携带context
和数据流目标,咱们能够基于数据流目标的数据来构建组件。
因而咱们要监听暗码输入框内容改变时,只需求运用一个StreamController
目标,将改变后的内容添加到数据流中。这样,当输入框内容改变时,就会触发StreamBuilder
改写,咱们从这个StreamController
目标取出最新数据来构建界面即可。这部分对应的代码如下。
final StreamController<String> _inputController = StreamController<String>();
// ...
@override
Widget build(BuildContext context) {
//...
TextField(
keyboardType: TextInputType.visiblePassword,
onChanged: (text) {
_inputController.add(text);
},
decoration: const InputDecoration(labelText: '请输入暗码'),
),
//...
StreamBuilder<String>(
stream: _inputController.stream,
initialData: '',
builder: (context, snapshot) {
final passwordStrength = calculateStrength(snapshot.data!);
return PasswordStrengthIndicator(
passwordStrength: passwordStrength, lineHeight: 4.0);
},
),
}
PasswordStrengthIndicator
是自界说的暗码指示器,完结的话是一个 Row
组件,经过 Flex 组件保持三段线(Container
) 等宽,代码比较简单,如下所示。其中PasswordStrength
是一个枚举,有 weak
、medium
和 strong
三个值,别离对应弱暗码、中等强度暗码和强暗码。
class PasswordStrengthIndicator extends StatelessWidget {
final PasswordStrength passwordStrength;
final double lineHeight;
const PasswordStrengthIndicator(
{super.key, required this.passwordStrength, required this.lineHeight});
final _strengthGapWidth = 8.0;
@override
Widget build(BuildContext context) {
var passwordIndicator =
PasswordIndicator(passwordStrength: passwordStrength);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
flex: 1,
child: Container(
height: lineHeight,
color: passwordIndicator.lineColors[0],
),
),
SizedBox(width: _strengthGapWidth),
Flexible(
flex: 1,
child: Container(
height: lineHeight,
color: passwordIndicator.lineColors[1],
),
),
SizedBox(width: _strengthGapWidth),
Flexible(
flex: 1,
child: Container(
height: lineHeight,
color: passwordIndicator.lineColors[2],
),
),
SizedBox(width: _strengthGapWidth),
Text(
passwordIndicator.strengthText,
style: TextStyle(
fontWeight: FontWeight.bold,
color: passwordIndicator.strengthTextColor,
),
),
],
);
}
}
PasswordIndicator
是一个自界说的实体类,主要是简化暗码强度指示器的代码,将组件显现所需求的数据全部封装到这个实体类中,包括线段显现的色彩,暗码强弱指示文字内容和文字色彩。代码如下:
class PasswordIndicator {
final PasswordStrength passwordStrength;
late List<Color> _lineColors;
late String _strengthText;
late Color _strengthTextColor;
PasswordIndicator({required this.passwordStrength}) {
switch (passwordStrength) {
case PasswordStrength.weak:
_lineColors = const [
Color(0xFFCCCCCC),
Color(0xFFCCCCCC),
Color(0xFFCCCCCC)
];
_strengthText = '弱';
_strengthTextColor = Colors.red;
break;
case PasswordStrength.medium:
_lineColors = const [
Color(0xFF00A52B),
Color(0xFF00A52B),
Color(0xFFCCCCCC)
];
_strengthText = '中等';
_strengthTextColor = Colors.orange;
break;
default:
_lineColors = const [
Color(0xFF00A52B),
Color(0xFF00A52B),
Color(0xFF00A52B)
];
_strengthText = '强';
_strengthTextColor = const Color(0xFF00A52B);
break;
}
}
get lineColors => _lineColors;
get strengthText => _strengthText;
get strengthTextColor => _strengthTextColor;
}
最终是暗码强度校验逻辑,这个运用办法calculateStrength
完结,其实这个也能够作为一个东西办法运用。办法界说如下,主要是经过正则来判别暗码的强弱。
PasswordStrength calculateStrength(String password) {
if (password.length >= 8) {
bool hasDigit = false;
bool hasLetter = false;
bool hasSpecial = false;
for (var char in password.split('')) {
if (RegExp(r'[0-9]').hasMatch(char)) {
hasDigit = true;
} else if (RegExp(r'[A-Za-z]').hasMatch(char)) {
hasLetter = true;
} else {
hasSpecial = true;
}
}
if (hasDigit && hasLetter && hasSpecial) {
return PasswordStrength.strong;
} else if ((hasDigit && hasLetter) ||
(hasDigit && hasSpecial) ||
(hasLetter && hasSpecial)) {
return PasswordStrength.medium;
}
}
return PasswordStrength.weak;
}
}
完好代码
完好代码现已上传至gitee:Flutter有用组件源码。
我是岛上码农,微信公众号同名。如有问题能够加自己微信沟通,微信号:
island-coder
。:觉得有收获请点个赞鼓舞一下!
:保藏文章,方便回看哦!
:谈论沟通,互相前进!