The GetX architecture is adopted as a whole, and it is very simple to control the status of verification code with GetX responsiveness

Take a look at the Logic layer

class MobileLoginLogic extends GetxController { RxBool showClear = false.obs; RxBool codeEnable = false.obs; RxBool checkBox = false.obs; RxBool loginBtnEable = false.obs; /// Count down the timer. late Timer _timer; // the number of seconds in the current countdown. late int _seconds = 20; late bool needRestTime; RxString verifyStr = 'obtain verification code '. Obs; TextEditingController mobileMemberController = TextEditingController(); TextEditingController codeController = TextEditingController(); final formKey = GlobalKey<FormState>(); late String identifierForVendor; @override void onReady() { // TODO: implement onReady super.onReady(); mobileMemberController.addListener(() { showClear.value = mobileMemberController.text.isNotEmpty; codeEnable.value = chinaPhoneNumber(mobileMemberController.text); setLoginBtnStatus(); }); codeController.addListener(() { setLoginBtnStatus(); }); initPlatformState(); } Future<void> initPlatformState() async { DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); if (Platform.isIOS) { IosDeviceInfo iosDeviceInfo = await deviceInfoPlugin.iosInfo; identifierForVendor = iosDeviceInfo.identifierForVendor; } } setLoginBtnStatus(){ if (mobileMemberController.text.length>=3) { loginBtnEable.value = true; }else{ loginBtnEable.value = false; } } clearField() { showClear.value = false; mobileMemberController.clear(); } checkArgement(){ checkBox.value = ! checkBox.value; } /// Cancel the countdown timer. void _cancelTimer() { _timer.cancel(); } /// Start the countdown timer. Void startTimer() {// Periodic (' periodic ') constructor of the Timer(' Timer ') component, creates a new repeating Timer. _timer = Timer.periodic(Duration(seconds: 1), (timer) { if (_seconds == 0) { _cancelTimer(); _seconds = 20; Verifystr. value = 'resend '; codeEnable.value = true; return; } _seconds--; Verifystr. value = 'sent $_seconds' + 's'; codeEnable.value = false; }); } chageCodeStatus(){ if (codeEnable.value) { startTimer(); } } bool chinaPhoneNumber(String input) { String regexPhoneNumber = "^ ([0-9] (13) | | (15 [^ 4]) (166) | | (17 [0 to 8]) (18 [0-9]) | | (19 [8-9]) (147145)) \ \ d {8} \ $"; return RegExp(regexPhoneNumber).hasMatch(input); } loginClick() async{ if (! loginBtnEable.value) return; print(identifierForVendor); Fluttertoast. ShowToast (MSG: 'log in', gravity: ToastGravity. CENTER, toastLength: Toast. LENGTH_LONG); try{ var response = await Dio().post('',data: { 'token':mobileMemberController.text, 'imei':identifierForVendor }); Map<String,dynamic> data = response.data; if (data["code"] == 200) { StorageManager.sharedPreferences.setString(StorageManager.access_token, mobileMemberController.text); UserModel userModel = UserModel.fromJson(data["data"]); StorageManager.localStorage.setItem(StorageManager.access_user, userModel); Get.offNamed(Routes.MAIN); }else{fluttertoast. showToast(MSG: 'login failed '); }}catch(e){fluttertoast.showtoast (MSG: 'login failed '); }}}Copy the code

Verification code separate statelessWidget

class VerifyCodeWidget extends StatelessWidget { final MobileLoginLogic logic = Get.put(MobileLoginLogic()); @override Widget build(BuildContext context) { return InkWell( onTap: () => logic.chageCodeStatus(), child: Obx(() => Container(padding: EdgeInsets. All (5.0), decoration: BoxDecoration(border: border. logic.codeEnable.value ? Color(0xFF0165B8) : Colors.white)), child: Text( logic.verifyStr.value, style: TextStyle(color: logic.codeEnable.value? Color(0xFF0165B8):Color(0xFFACB1B6)), ), )), ); }}Copy the code

Logic.codeenable. value controls whether clicking is allowed

Logic.verifystr. value controls the text to be displayed

The mobile phone number box displays the clear icon according to the content

TextFormField( controller: logic.mobileMemberController, inputFormatters: <TextInputFormatter>[ LengthLimitingTextInputFormatter(11) ], textInputAction: TextInputAction.next, keyboardType: Textinputtype. number, decoration: InputDecoration(labelText: 'Please enter your phone number ', labelStyle: TextStyle(color: color: RGB (50, 50, 50)) Color(0xFF898E92)), enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, suffixIcon: Obx(() => Visibility( visible: logic.showClear.value, child: IconButton( icon: Icon( CupertinoIcons.clear_thick_circled, color: Color(0xFFCBD0D4), ), onPressed: logic.clearField))))),Copy the code

SuffixIocn is a suffix-clear button controlled by Obx(() => Visibility()