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()