Flutter 輸入車牌號,驗證碼鍵盤效果

一天清晨發表於2021-03-26

驗證碼基本上是每個專案都需要用到的功能,這篇文章完成了一個驗證碼的輸入框效果,並且擴充了一個輸入上傳車牌號(包括新能源),自定義鍵盤等功能。作者會根據自己的實現的思路來闡述一下功能的實現

驗證碼輸入的實現

先看一下效果

tutieshi_640x1343_6s.gif 實現思路是:

首先讓鍵盤彈起來

使用TextField讓鍵盤彈起來,並且通過設定TextField的屬性,讓使用者感覺不到TextField的存在

TextField(
  maxLength: 6,
  onChanged: (value) {
  },
  controller: controller,
  cursorWidth: 0,
  cursorColor: Colors.transparent,
  keyboardType: TextInputType.number,
  style: TextStyle(color: Colors.transparent),
         decoration: InputDecoration(
           border: InputBorder.none,
           counterText: '',
         ),
 ),
複製程式碼

這樣就完全看不到TextField 的存在並且點選可以彈起鍵盤

展示輸入的驗證碼

使用stack佈局,在最低層構建一排container設定邊框,然後將TextField放在其上面,這樣就會可以了,再監聽onChanged方法,進行遍歷TextField的輸入值,顯示在一排排的container上面。

Stack(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: dataList
                        .map<Widget>((e) => renderContainer(e))
                        .toList(),
                  ),
                  TextField(
                    maxLength: 6,
                    onChanged: (value) {
                      List data = [];
                      for (int i = 0; i < value.length; i++) {
                        data.add(value.substring(i, i + 1));
                      }
                      data = fillData(data);
                      if (mounted) {
                        setState(() {
                          dataList = data;
                        });
                      }
                    },
                    controller: controller,
                    cursorWidth: 0,
                    cursorColor: Colors.transparent,
                    keyboardType: TextInputType.number,
                    style: TextStyle(color: Colors.transparent),
                    decoration: InputDecoration(
                      border: InputBorder.none,
                      counterText: '',
                    ),
                  ),
                ],
              )
複製程式碼

基本程式碼完成了,下面是全部程式碼

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';

class CarInputPage extends StatefulWidget {
  CarInputPage({Key key}) : super(key: key);

  @override
  _CarInputPageState createState() => _CarInputPageState();
}

class _CarInputPageState extends State<CarInputPage> {
  TextEditingController controller = TextEditingController();
  List dataList = ['', '', '', '', '', ''];

  renderContainer(title) {
    return Container(
      width: 60,
      height: 80,
      alignment: Alignment.center,
      decoration: BoxDecoration(
          border: Border.all(
              color: title == '' ? Colors.green : Colors.blue, width: 2)),
      child: Text(
        title,
        style: TextStyle(fontSize: 18, color: Colors.blue),
      ),
    );
  }

  List fillData(List data) {
    if (data.length < 6) {
      data.add('');
      this.fillData(data);
    }
    return data;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: customAppbar(title: '繫結車輛'),
      body: GestureDetector(
        onTap: () {
          print('object');
          SystemChannels.textInput.invokeMethod('TextInput.hide');
        },
        child: Container(
          width: Get.width,
          decoration: BoxDecoration(color: Colors.white),
          padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
          child: Column(
            children: [
              Stack(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: dataList
                        .map<Widget>((e) => renderContainer(e))
                        .toList(),
                  ),
                  TextField(
                    maxLength: 6,
                    onChanged: (value) {
                      List data = [];
                      for (int i = 0; i < value.length; i++) {
                        data.add(value.substring(i, i + 1));
                      }
                      data = fillData(data);
                      if (mounted) {
                        setState(() {
                          dataList = data;
                        });
                      }
                    },
                    controller: controller,
                    cursorWidth: 0,
                    cursorColor: Colors.transparent,
                    keyboardType: TextInputType.number,
                    style: TextStyle(color: Colors.transparent),
                    decoration: InputDecoration(
                      border: InputBorder.none,
                      counterText: '',
                    ),
                  ),
                ],
              )
            ],
          ),
        ),
      ),
    );
  }
}
複製程式碼

可以上面的效果

自定義車牌號鍵盤

其中第一部分是每個省份的簡寫,之後就是字母和陣列的組合。 使用自定義彈出懸浮窗。這次就不需要使用TextField進行彈出操作,在stack佈局上新增點選方法就可以了。(ps: 資料來源有可能不準確)

Simulator Screen Shot - iPhone 11 - 2021-03-25 at 17.28.43.png

Get.dialog(StatefulBuilder(
                              builder: (context1, setBottomSheetState) {
                        return UnconstrainedBox(
                          alignment: Alignment.bottomCenter,
                          child: Container(
                              padding: EdgeInsets.only(
                                  bottom: Get.context.mediaQueryPadding.bottom),
                              width: Get.width,
                              decoration: BoxDecoration(
                                color: Colors.white,
                              ),
                              child: Wrap(
                                children: keybordData
                                    .map<Widget>((e) =>
                                        renderNumberOne(e, setBottomSheetState))
                                    .toList(),
                              )),
                        );
                      }),
                          barrierColor: Colors.transparent,
                          useRootNavigator: false,
                          useSafeArea: false);
複製程式碼

自定義鍵盤與資料展示的聯動

下面展示的是點選切換鍵盤效果,主要實現思路是,控制自定義鍵盤內的資料,通過type區分展示不同的資料。 tutieshi_640x1343_11s.gif

fillData(title) {
if (dataList.length > 7) {
      return;
    }
    List temp = dataList;
    int index = -1;
    for (int i = 0; i < temp.length; i++) {
      if (temp[i] == '' || temp[i] == '新') {
        index = i;
        break;
      }
    }
    if (index != -1) {
      temp[index] = title;
    }
    setState(() {
      dataList = temp;
    });
  }

renderNumberOne(title, setBottomSheetState) {
    return Container(
      alignment: Alignment.center,
      width: Get.width / 8,
      height: Get.width / 8 * 1.2,
      decoration: BoxDecoration(
        border: Border.all(width: 1, color: Colors.grey),
      ),
      child: Material(
          child: InkWell(
        onTap: () {
          if (type == 0) {
            //選擇省份
            List temp = dataList;
            temp[0] = title;
            setBottomSheetState(() {
              type = 1;
              keybordData = wordList;
            });
            setState(() {
              dataList = temp;
            });
          } else if (type == 1) {
            if (title == '0~9') {
              setBottomSheetState(() {
                type = 2;
                keybordData = numberList;
              });
            } else {
              fillData(title);
            }
          } else if (type == 2) {
            if (title == 'A~Z') {
              setBottomSheetState(() {
                type = 1;
                keybordData = wordList;
              });
            } else {
              fillData(title);
            }
          }
        },
        child: title == '刪除'
            ? Icon(
                Icons.delete,
                size: 18,
              )
            : Text(
                title,
                style: TextStyle(fontSize: 16, color: Colors.black),
              ),
      )),
    );
  }
複製程式碼

最後就是點選刪除按鈕的邏輯

deleData(title, setBottomSheetState) {
    List temp = dataList;
    int index = -1;
    for (int i = 0; i < temp.length; i++) {
      if (temp[i] != '' && temp[i] != '新') {
        index = i;
      }
    }
    if (index != -1) {
      temp[index] = index == 6 ? '新' : '';
    }
    if (index == 0) {
      setBottomSheetState(() {
        type = 1;
        keybordData = province;
      });
    }
    setState(() {
      dataList = temp;
    });
  }
複製程式碼

效果:

tutieshi_640x1343_9s.gif over~~~

相關文章