撸一个优雅的Flutter验证码Widget

前言

Flutter自带TextField组件无法满足现在主流UI的验证码界面的要求(特别是4,6位纯数字的验证码组件),即使是在iOS下原生的实现方案也是多采用自定义UIView的方式实现。本文作者曾经尝试改进Flutter自带的TextField想实现此界面多存在如下问题。

  1. 采用1个自带的TextField,通过计算Cursor光标的位移实现,最终发现一些问题,比如在安卓和iOS下位移不统一(有可能是字体不统一影响到),特别是Cursor的高度没有暴露属性,不能设置,只能通过改变TextField的FontSize能影响到Curosr的高度,

  2. 采用多个TextField,UI问题很容易解决,但是要通过计算输入了多少个文字,不停的切换FocusNode(在iOS上面来说就是要不停切换第一响应者,键盘才能知道你当前输入的哪个TextField),此方法看起来可行,但是实际上Flutter对FocusNode的一些监听,包括键盘通知等(iOS可以自行通过插件实现,安卓据我所知没有那么方便的Api基本是靠Windows改变之类的监听代实现),不太友好,已经这类监听说到底偏向硬件底层,Flutter始终是一个UI引擎,很多系统实现都是人工通过插件实现的,这方面生态仍需加强。

  3. 第三种方案也就是目前下文采用的方案,通过查看Flutter的TextField源码得知,它的Cursor光标闪烁动画,实际上就是一个Timer轮训,不停的改变透明度0-1-0 这样。我们何不如把光标的隐藏(showCursor = false)即可,自实现一个闪烁的光标呢?这就是下文的优雅的验证码Widget 而来。有兴趣的伙伴也可以下载下来查看一下源码,目前兼容两种市面上使用非常广泛的模式,实际上非常简单。

另外: auth_code_textfiled 也已经发布到pub,有需要的开发者只需要:

dependencies:
  auth_code_textfield: ^0.0.2

即可集成。下面介绍一部分auth_code_textfiled的简单用法与示例。

Useage

Mode: singleItem , like Keep

Item模式,如Keep的风格。

AuthCodeTextfield(
                  mode: AuthCodeMode.singleItem,
                  itemWidth: 50,
                  itemHeight: 50,
                  itemSpacing: 35 * scaleWidth,
                  itemBackgroundColor: Color.fromRGBO(120, 114, 127, 1),
                  textColor: Colors.white,
                  cursorColor: Color.fromRGBO(94,178,138,1),
                  onChanged: (s) {
                    setState(() {
                      _inputText = s;
                    });
                  },
                ),
iOS Android

Mode: bottomLine , like DingDing

bottomLine模式,如钉钉的风格。

AuthCodeTextfield(
                  mode: AuthCodeMode.bottomLine,
                  itemWidth: 50,
                  itemHeight: 60,
                  itemSpacing: 35 * scaleWidth,
                  itemBottomLineColor: Color.fromRGBO(229, 231, 233, 1),
                  cursorWidth: 1,
                  cursorHeight: 30,
                  onChanged: (s) {
                    _inputText = s;
                    if (s.toString().length >= 4 && widget.onSubmited != null) {
                      widget.onSubmited(_inputText);
                      Navigator.pop(context);
                    }
                  },
                ),
iOS Android

发表评论

电子邮件地址不会被公开。 必填项已用*标注