碼一個驗證碼的輸入框,實現效果如下:
實現思路
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;
}
}
},
複製程式碼
還有一些需求比如方形框選擇,這裡就沒有新增了,後續可能用到的時候會新增介面,需要的話可以拉下來改一下原始碼就好