Flutter實現(xiàn)密碼強度校驗結(jié)果的示例詳解
前言
我們經(jīng)常在一些網(wǎng)站上看到這樣的密碼強度指示,使用三段線,分別用不同的顏色來表示弱密碼、中等強度密碼和強密碼。這種方式能夠讓用戶清晰地感知到自己設(shè)置密碼的強度,體驗上更為友好。本篇我們就用 Flutter 來實現(xiàn)這樣一個密碼強度校驗示例。最終完成的效果如下圖。

組件分析
這里面實際上是密碼強度要動態(tài)隨密碼輸入框的內(nèi)容改變,因此需要監(jiān)聽輸入框內(nèi)容的變化。常規(guī)的做法是在輸入框的 onChanged 方法里 setState 來更新整個組件。但是,實際上有更優(yōu)雅的實現(xiàn)方式,那就是使用 Dart 的Stream 來實現(xiàn)局部刷新,也就是輸入內(nèi)容變化時只刷新密碼強度指示區(qū)域。稍后我們會講具體的實現(xiàn)。 界面上,實際上組件的層級關(guān)系如下圖所示。

為了簡化嵌套層級,我們將框起來的部分,也就是密碼強度指示單獨封裝成一個組件,叫做PasswordStrengthIndicator。這個組件也就是需要跟隨文本輸入框內(nèi)容變化而局部刷新的組件。這里順帶說一下,如果要考慮局部刷新,那么就需要合理的封裝組件,將需要局部刷新的組件和不需要刷新的部分拆分開,這樣就能夠在最小范圍控制要刷新的組件。 最后是密碼強度校驗的邏輯,我們的邏輯如下:
- 密碼長度低于8或者只包含數(shù)字、字母和特殊字符中的一個,則認(rèn)為是弱密碼;
- 密碼長度大于8,且只包含數(shù)字、字母和特殊字符中的兩個,則認(rèn)為是中等強度密碼;
- 密碼長度大于8,且同時包含數(shù)字、字母和特殊字符,則認(rèn)為是強密碼。
這個邏輯可以通過正則匹配來完成。 最后是密碼強度指示組件的實現(xiàn),我們要保證三段線等寬且等比例,那么就可以用一個 Flex 組件包裹一個 Container 組件,設(shè)置比例 flex 值為1,就可以了。這樣做法的好處是不需要寫死 Container 的寬度,適用性更強。
代碼實現(xiàn)
我們先來看一下 Stream 如何實現(xiàn)局部刷新。在 Flutter 里,提供了一個 基于 Stream 構(gòu)建組件的 StreamBuilder類。當(dāng)StreamBuilder監(jiān)聽到 Stream 內(nèi)容發(fā)生變化時,就會調(diào)用其builder方法重新構(gòu)建一個組件并返回。StreamBuilder的定義如下:
const StreamBuilder({
super.key,
this.initialData,
super.stream,
required this.builder,
});這是一個泛型類,因此可以接收任何類型的數(shù)據(jù),比如我們自定義的業(yè)務(wù)對象。其中各個參數(shù)說明如下:
initialData是初始值;stream即要監(jiān)聽的數(shù)據(jù)流,通常由一個StreamController提供(也可以是網(wǎng)絡(luò)數(shù)據(jù)流)。builder即組件構(gòu)建方法,該方法會攜帶context和數(shù)據(jù)流對象,我們可以基于數(shù)據(jù)流對象的數(shù)據(jù)來構(gòu)建組件。
因此我們要監(jiān)聽密碼輸入框內(nèi)容變化時,只需要使用一個StreamController對象,將變化后的內(nèi)容添加到數(shù)據(jù)流中。這樣,當(dāng)輸入框內(nèi)容變化時,就會觸發(fā)StreamBuilder刷新,我們從這個StreamController對象取出最新數(shù)據(jù)來構(gòu)建界面即可。這部分對應(yīng)的代碼如下。
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是自定義的密碼指示器,實現(xiàn)的話是一個 Row 組件,通過 Flex 組件保持三段線(Container) 等寬,代碼比較簡單,如下所示。其中PasswordStrength是一個枚舉,有 weak、medium 和 strong 三個值,分別對應(yīng)弱密碼、中等強度密碼和強密碼。
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是一個自定義的實體類,主要是簡化密碼強度指示器的代碼,將組件顯示所需要的數(shù)據(jù)全部封裝到這個實體類中,包括線段顯示的顏色,密碼強弱指示文字內(nèi)容和文字顏色。代碼如下:
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實現(xiàn),其實這個也可以作為一個工具方法使用。方法定義如下,主要是通過正則來判斷密碼的強弱。
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;
}
}完整代碼
完整代碼已經(jīng)上傳至gitee:Flutter實用組件源碼。
到此這篇關(guān)于Flutter實現(xiàn)密碼強度校驗結(jié)果的示例詳解的文章就介紹到這了,更多相關(guān)Flutter密碼強度校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
FragmentStatePagerAdapter保存恢復(fù)下拉刷新Fragment內(nèi)存數(shù)據(jù)
這篇文章主要為大家介紹了FragmentStatePagerAdapter保存恢復(fù)下拉刷新Fragment內(nèi)存數(shù)據(jù)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
Rxjava2_Flowable_Sqlite_Android數(shù)據(jù)庫訪問實例
下面小編就為大家分享一篇Rxjava2_Flowable_Sqlite_Android數(shù)據(jù)庫訪問實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02
android SectorMenuView底部導(dǎo)航扇形菜單的實現(xiàn)代碼
這篇文章主要介紹了android SectorMenuView底部導(dǎo)航扇形菜單的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02

