Verification code is basically a function that every project needs to use. This article has completed the effect of an input box of verification code, and expanded the functions of uploading license plate number (including new energy) and custom keyboard. The author will describe the realization of the function according to the ideas of their own implementation

Verification code input implementation

So let’s look at the effect

The realization idea is as follows:

First let the keyboard play

Use TextField to make the keyboard pop, and set the TextField properties so that the user does not feel its presence

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: ' ',),),Copy the code

So you can’t see the TextField at all and click on it to pop up the keyboard

Displays the entered verification code

Using the Stack layout, build a row of Containers on the lowest layer to set the border, and then place TextField on top of it so that it will work. Listen to the onChanged method to iterate over the TextField input values displayed on top of the rows of Containers.

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: ' '(), (],)Copy the code

The basic code is complete. Here is the complete code

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: 'Bound vehicle'),
      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: ' '() [() [() [() [() [() [() [() [() }}Copy the code

Can be the effect above

Custom license plate keypad

The first part is a shorthand for each province, followed by a combination of letters and arrays. Use custom pop-up hover Windows. Instead of using TextField for pop-ups, add click methods to the stack layout. (PS: The data source may be inaccurate)

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);
Copy the code

Custom keyboard and data display linkage

The following shows the effect of clicking to switch the keyboard. The main idea is to control the data in the custom keyboard and display different data through type.

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] == 'new') {
        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) {
            // Select the province
            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 == 'delete'
            ? Icon(
                Icons.delete,
                size: 18,
              )
            : Text(
                title,
                style: TextStyle(fontSize: 16, color: Colors.black),
              ),
      )),
    );
  }
Copy the code

Finally, there is the logic of hitting the delete button

deleData(title, setBottomSheetState) {
    List temp = dataList;
    int index = - 1;
    for (int i = 0; i < temp.length; i++) {
      if(temp[i] ! =' '&& temp[i] ! ='new') { index = i; }}if(index ! =- 1) {
      temp[index] = index == 6 ? 'new' : ' ';
    }
    if (index == 0) {
      setBottomSheetState(() {
        type = 1;
        keybordData = province;
      });
    }
    setState(() {
      dataList = temp;
    });
  }
Copy the code

Effect:

over~~~