实现效果如下:
example.gif实现思路
1.选用控件:TextField
这里选择使用4/6个TextField
,隐藏光标,设置TextField
样式
decoration: InputDecoration(
hintStyle: TextStyle(color: Color(0xff8C8C8C), fontSize: 14),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFFFD3B60), width: 1)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xffDADADA), width: 1)),
fillColor: Colors.transparent,
filled: true,
)
存储数据使用两个list,一个存储值,一个存储焦点
List<FocusNode> focusNodeList = [];
List<String> textList = [];
2.处理焦点跳转逻辑
输入完一个字符后跳转到下一个TextField
,最后一个输入完成后失去焦点,收起键盘
onChanged: (value) {
...
textList[index] = value;
//焦点后移
if (index < focusNodeList.length - 1) {
_getFocus(focusNodeList[index + 1]);
textList[index + 1] = ' ';
} else {
_loseFocus(focusNodeList[index]);
}
setState(() {});
textChanged(textList);
...
},
3.处理复制验证码逻辑
当检测输入为粘贴的数据时,直接填充
//输入值为复制的验证码
//输入值为复制的验证码
if (value.length == itemCount || value.length == itemCount + 1) {
if (value.length == itemCount + 1) {
if (oldStr == value.substring(0, 1)) {
//删除第一位
value = value.substring(1);
} else {
//删除最后一位
value = value.substring(0, value.length - 1);
}
}
//所有重新赋值
for (int i = 0; i < textList.length; i++) {
textList[i] = value.substring(i, i + 1);
}
_loseFocus(focusNodeList[index]);
setState(() {});
textChanged(textList);
return;
}
4.处理删除按键逻辑
当TextField
获取焦点没有值时,按删除按钮onChanged
方法是没有响应的,我这里的处理方式是在焦点跳转到下一个输入框的时候先插入一个空白字符,用以捕获删除按钮点击。
textList[i + 1] = ' ';
5.禁用可选事件
到这里基本实现了点击效果,但是产品出不能让用户自由选择单个输入框,只能是依次输入或者依次删除。
这里我在输入框上面盖了一个透明的View,然后处理它的点击事件
GestureDetector(
onTap: () {
for (int i = textList.length - 1; i >= 0; i--) {
String text = textList[i];
if ((text.length > 0 && text != ' ') || i == 0) {
if (i < textList.length - 1 && i != 0) {
_getFocus(focusNodeList[i + 1]);
if (textList[i + 1].length == 0) {
textList[i + 1] = ' ';
}
} else if (i == textList.length - 1) {
_getFocus(focusNodeList[i]);
} else {
_getFocus(focusNodeList[0]);
}
break;
}
}
},
还有一些需求比如方形框选择,这里就没有添加了,后续可能用到的时候会添加接口,需要的话可以拉下来改一下源码就好
网友评论