8

Flutter 完美的验证码输入框

 4 years ago
source link: https://segmentfault.com/a/1190000022310280
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

VF7Jrii.png!web

老孟导读:刚开始看到这个功能的时候一定觉得so easy,开始的时候我也是这么觉得的,这还不简单,然而真正写的时候才发现并没有想象的那么简单。

先上图,不上图你们都不想看,我难啊,到Github: https://github.com/781238222/flutter-do 上给个小星星可还行,如果能fork一下,那更是感激不尽。

<center class="half">

<img src="http://img.laomengit.com/verification_box_6.gif" width="250"/>
<img src="http://img.laomengit.com/verification_box_7.gif" width="250"/>

<img src="http://img.laomengit.com/verification_box_8.gif" width="250"/>

</center>

言归正传,完成验证码输入框经历了4个阶段,虽然前3个尝试是失败的,但也想和大家分享下,避免大家再走弯路。

第一阶段:开始的时候,我认为直接修改TextField控件,改改外观就可以了,所以我就直接去改TextField的属性,研究了一遍,发现无法达到要求,系统提供的属性无法达到我的要求。

第二阶段:既然原生的TextField无法实现我的效果,那就重写一个(并不是全部重写,而是把源代码copy出来,修改控制外观的代码),于是我就去copy源代码了,可真正copy的时候发现TextField的关系比较复杂,并不是一个简单的 StatefulWidget 控件,而且需要计算字符的宽度,此方案虽然能实现,但想想就复杂,果断抛弃。

第三阶段:用6个TextField,每一个控制一个验证码,虽然样式及布局上很容易达到要求,但焦点控制问题非常致命,此方案也pass。

第四阶段:经过上面失败的经历,最后我才用如下方案:一个TextField用于输入,而验证码的显示使用 Container ,验证码覆盖在TextField之上,用户无法感知到TextField,这是目前为止我发现的最完美的方案。

焦点问题

正常情况下,出现验证码的页面会弹出键盘,此效果很好实现,指需给TextField指定自动获取焦点即可,代码如下:

TextField(
    autofocus:true,
    ...
)

如果页面还有其他输入框,那么就不一定要获取焦点了,因此是否获取焦点需要交给用户来决定。

如果开始没有获取焦点就出现了一个问题,用户点击“验证码”的时候需要获取焦点,获取焦点方法如下:

GestureDetector(
  onTap: () {
    FocusScope.of(context).requestFocus(_focusNode);
  },
  ...
)

给整个控件的外层添加点击事件, _focusNode 为TextField的 focusNode

输入完成后,通常需要关闭键盘,即TextField失去焦点,失去焦点方法如下:

_focusNode.unfocus();

使用

使用非常简单,如下:

Container(
  height: 45,
  child: VerificationBox(),
)

效果如下:

<img src="http://img.laomengit.com/verification_box_1.png" style="zoom:33%;" />

设置验证码的数量,比如设置4个:

VerificationBox(
  count: 4,
)

效果如下:

FZFZji6.png!web

设置样式,包括边框的颜色、宽度、圆角:

VerificationBox(
  borderColor: Colors.lightBlue,
  borderWidth: 3,
  borderRadius: 50,
)

效果如下:

r6jyIzb.png!web

除了“盒子”样式,还支持下划线样式:

VerificationBox(
  type: VerificationBoxItemType.underline,
)

效果如下:

nmyYf2n.png!web

设置数字的样式:

VerificationBox(
  textStyle: TextStyle(color: Colors.lightBlue),
)

效果如下:

mMnQ7bZ.png!web

显示光标,设置光标样式:

VerificationBox(
  showCursor: true,
  cursorWidth: 2,
  cursorColor: Colors.red,
  cursorIndent: 10,
  cursorEndIndent: 10,
)

效果如下:

<img src="http://img.laomengit.com/verification_box_6.gif" style="zoom:33%;" />

还可以设置光标为整个边框,如下:

VerificationBox(
  focusBorderColor: Colors.lightBlue,
)

效果如下:

<img src="http://img.laomengit.com/verification_box_7.gif" style="zoom:33%;" />

终极大招,如果你觉得这个效果不好,你可以自定义 decoration

VerificationBox(
    decoration: BoxDecoration(
      image: DecorationImage(image: AssetImage('images/box.png')),
    ),
    textStyle: TextStyle(color: Colors.lightBlue),
  ),
)

效果如下:

<img src="http://img.laomengit.com/verification_box_8.gif" style="zoom:33%;" />

验证码输入完成后回调 onSubmitted ,用法如下:

VerificationBox(
  onSubmitted: (value){
    print('$value');
  },
)

输入完成后,默认键盘消失,设置为不消失,代码如下:

VerificationBox(
  unfocus: false,
)

交流

如果你对Flutter还有疑问或者技术方面的疑惑,欢迎加入Flutter交流群(微信:laomengit)。

同时也欢迎关注我的Flutter公众号【老孟程序员】,公众号首发Flutter的相关内容。

Flutter地址: http://laomengit.com 里面包含160多个组件的详细用法。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK