總體採用GetX架構,使用getx響應式控制驗證碼狀態很簡單ios
先看下logic層markdown
class MobileLoginLogic extends GetxController {
RxBool showClear = false.obs;
RxBool codeEnable = false.obs;
RxBool checkBox = false.obs;
RxBool loginBtnEable = false.obs;
/// 倒計時的計時器。
late Timer _timer;
/// 當前倒計時的秒數。
late int _seconds = 20;
late bool needRestTime;
RxString verifyStr = '獲取驗證碼'.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;
}
/// 取消倒計時的計時器。
void _cancelTimer() {
_timer.cancel();
}
/// 啓動倒計時的計時器。
void startTimer() {
// 計時器(`Timer`)組件的按期(`periodic`)構造函數,建立一個新的重複計時器。
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
if (_seconds == 0) {
_cancelTimer();
_seconds = 20;
verifyStr.value = '從新發送';
codeEnable.value = true;
return;
}
_seconds--;
verifyStr.value = '已發送$_seconds' + 's';
codeEnable.value = false;
});
}
chageCodeStatus(){
if (codeEnable.value) {
startTimer();
}
}
bool chinaPhoneNumber(String input) {
String regexPhoneNumber =
"^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$";
return RegExp(regexPhoneNumber).hasMatch(input);
}
loginClick() async{
if (!loginBtnEable.value) return;
print(identifierForVendor);
Fluttertoast.showToast(msg: '登陸中',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: '登陸失敗');
}
}catch(e){
Fluttertoast.showToast(msg: '登陸失敗');
}
}
}
複製代碼
驗證碼單獨的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.all(
color: logic.codeEnable.value
? Color(0xFF0165B8)
: Colors.white)),
child: Text(
logic.verifyStr.value,
style: TextStyle(color: logic.codeEnable.value?Color(0xFF0165B8):Color(0xFFACB1B6)),
),
)),
);
}
}
複製代碼
經過logic.codeEnable.value 控制是否能夠點擊less
logic.verifyStr.value 控制顯示的文本async
手機號框根據內容顯示清空圖標ide
TextFormField(
controller: logic.mobileMemberController,
inputFormatters: <TextInputFormatter>[
LengthLimitingTextInputFormatter(11)
],
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: '請輸入手機號',
labelStyle: TextStyle(color: 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))))),
複製代碼
suffixIocn是後綴清除按鈕 經過 Obx(() => Visibility()控制是都顯示函數