Flutter实现密码强度校验结果的示例详解

 更新时间:2023年08月10日 14:25:23   作者:岛上码农  
我们经常在一些网站上看到这样的密码强度指示,使用三段线,分别用不同的颜色来表示弱密码、中等强度密码和强密码,本篇我们就用 Flutter 来实现这样一个密码强度校验示例,希望对大家有所帮助

前言

我们经常在一些网站上看到这样的密码强度指示,使用三段线,分别用不同的颜色来表示弱密码、中等强度密码和强密码。这种方式能够让用户清晰地感知到自己设置密码的强度,体验上更为友好。本篇我们就用 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是一个枚举,有 weakmediumstrong 三个值,分别对应弱密码、中等强度密码和强密码。

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实用组件源码

到此这篇关于Flutter实现密码强度校验结果的示例详解的文章就介绍到这了,更多相关Flutter密码强度校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • [Android] 通过GridView仿微信动态添加本地图片示例代码

    [Android] 通过GridView仿微信动态添加本地图片示例代码

    本篇文章主要介绍了[Android] 通过GridView仿微信动态添加本地图片示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • Android基于MLKit实现条形码扫码的代码示例

    Android基于MLKit实现条形码扫码的代码示例

    这篇文章将借助开源库 MLKit 实现条形码扫描,对于商品条形码也可以很好地识别成功,该库的使用内容非常丰富,除了条码识别,还有文字识别、图像标记、人脸检测等等,本文篇文章就只介绍最基本的条形码扫描使用,需要的朋友可以参考下
    2023-08-08
  • Android getSystemService用法实例总结

    Android getSystemService用法实例总结

    这篇文章主要介绍了Android getSystemService用法,结合实例形式总结分析了getSystemService获取系统Service的相关使用方法与注意事项,需要的朋友可以参考下
    2016-01-01
  • 详解Android Ashmem匿名共享内存

    详解Android Ashmem匿名共享内存

    这篇文章主要介绍了Android Ashmem匿名共享内存的相关资料,帮助大家更好的理解和学习使用Android开发,感兴趣的朋友可以了解下
    2021-04-04
  • Android shape 绘制图形的实例详解

    Android shape 绘制图形的实例详解

    这篇文章主要介绍了Android shape 绘制图形的实例详解的相关资料,需要的朋友可以参考下
    2017-07-07
  • android文件上传示例分享(android图片上传)

    android文件上传示例分享(android图片上传)

    最近在做项目是用到Android上传功能,就写了个Android上传组件,支持拍照录用录视频和选择文件,需要的朋友可以参考下
    2014-04-04
  • Android自定义View获取注册验证码倒计时按钮

    Android自定义View获取注册验证码倒计时按钮

    这篇文章主要介绍了Android自定义View获取验证码倒计时按钮的制作方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • 浅谈RxJava+Retrofit+OkHttp 封装使用

    浅谈RxJava+Retrofit+OkHttp 封装使用

    本篇文章主要介绍了浅谈RxJava+Retrofit+OkHttp 懒人方式使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • 浅谈Android程序与JavaScript脚本的交互

    浅谈Android程序与JavaScript脚本的交互

    这篇文章主要介绍了Android程序与JavaScript的脚本交互,利用js开发安卓应用也是近来的热门话题,特别是随着Facebook的React Native的开源及对Android的官方支持,需要的朋友可以参考下
    2016-04-04
  • android底部菜单栏实现原理与代码

    android底部菜单栏实现原理与代码

    底部菜单栏很重要,我看了一下很多应用软件都是用了底部菜单栏做,我这里使用了tabhost做了一种通用的(就是可以像微信那样显示未读消息数量的,虽然之前也做过但是layout下的xml写的太臃肿,这里去掉了很多不必要的层,个人看起来还是不错的,所以贴出来方便以后使用
    2013-01-01

最新评论