import 'dart:async';
import 'package:cash_sys/base/base_state.dart';
import 'package:cash_sys/base/base_widget.dart';
import 'package:cash_sys/res/colors/colors.dart';
import 'package:cash_sys/res/string/strings_key.dart';
import 'package:cash_sys/res/string/stringutils.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_check_box_rounded/flutter_check_box_rounded.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:flutter_svg/flutter_svg.dart';
class RegisterPage extends BasePageWidget {
@override
State<StatefulWidget> createState() {
return _RegisterPageState();
}
@override
String get pageName => "登录界面";
}
class _RegisterPageState extends BaseState<RegisterPage> {
//切换账号注册和手机注册
bool isRightSelected = false;
// 第几个TextField获取焦点
int currentFocusIndex = -1;
late List focusNodes;
late List textEditingControllers;
/// 用户点击条款和隐私政策
bool termsSelected = false;
/// 设置注册按钮是否可用
// bool registerButtonEnabled = false;
/// 校验账号注册,用户名输入规则
bool input0Error = true;
bool isInit0 = false;
/// 校验账号注册,密码输入规则
bool input1Error = true;
bool input1Error1 = true;
bool input1Error2 = true;
bool input1Error3 = true;
// 是否包含小写字母
bool passwordStrength1 = false;
// 是否包含大写字母
bool passwordStrength2 = false;
// 是否包含数字
bool passwordStrength3 = false;
// 是否包含特殊字符
bool passwordStrength4 = false;
// 输入内容的长度
double passwordStrength5 = 0;
bool isInit1 = false;
///账号注册,输入密码明文密文的转变
// bool passwordIsObscure = true;
ValueNotifier<bool> passwordIsObscure = ValueNotifier<bool>(true);
///账号注册,再次输入密码明文密文的转变
bool passwordAgainObscure = true;
// ValueNotifier<bool> passwordAgainObscure = ValueNotifier<bool>(true);
///判断两次输入的密码是否一致,password是密码框内容,enterPassword是再次输入密码框的内容
String password = "";
String againPassword = "";
///邀请码输入框输入内容停止一秒后发起网络请求
Timer? _timer;
final Duration _inputDuration = const Duration(seconds: 1);
bool input3Error = false;
String inputText3 = "";
///手机注册 手机号是否可用
bool input4Error = false;
// 选中的文字
int selectedCountryIndex = 0;
// 是否弹出弹窗
bool isShowPopup = false;
//布局内容
List<String> popupList = [];
///手机验证码格式
//是否输入错误
bool input5Error = false;
//倒计时
late Timer _countDownTimer;
int _seconds = 60;
void updateSelection(bool isRight) {
setState(() {
isRightSelected = isRight;
});
}
void updateTermsState(bool selected) {
setState(() {
termsSelected = selected;
});
}
void requestFocus(int index) {
if (index >= 0 && index < focusNodes.length) {
setState(() {
currentFocusIndex = index;
});
FocusScope.of(context).requestFocus(focusNodes[index]);
}
}
void _validateInput0() {
setState(() {
if (!isInit0) {
isInit0 = true;
} else {
input0Error = !_isValidateInput0(textEditingControllers[0].text);
}
});
}
void _validateInput1() {
setState(() {
if (!isInit1) {
isInit1 = true;
} else {
input1Error1 = !_isValidateInput1_1(textEditingControllers[1].text);
input1Error2 = !_isValidateInput1_2(textEditingControllers[1].text);
input1Error3 = !_isValidateInput1_3(textEditingControllers[1].text);
passwordStrength1 = _passwordStrength1(textEditingControllers[1].text);
passwordStrength2 = _passwordStrength2(textEditingControllers[1].text);
passwordStrength3 = _passwordStrength3(textEditingControllers[1].text);
passwordStrength4 = _passwordStrength4(textEditingControllers[1].text);
passwordStrength5 =
_passwordStrength5(textEditingControllers[1].text.length);
if (kDebugMode) {
print("input1Error1:${input1Error1}");
print("input1Error2:${input1Error2}");
print("input1Error3:${input1Error3}");
}
input1Error = input1Error1 || input1Error2 || input1Error3;
}
});
}
bool _passwordStrength1(String input) {
RegExp regExp = RegExp(r'[a-z]');
return regExp.hasMatch(input);
}
bool _passwordStrength2(String input) {
RegExp regExp = RegExp(r'[A-Z]');
return regExp.hasMatch(input);
}
bool _passwordStrength3(String input) {
RegExp regExp = RegExp(r'\d');
return regExp.hasMatch(input);
}
bool _passwordStrength4(String input) {
RegExp regExp = RegExp(r'[!@#\$]');
return regExp.hasMatch(input);
}
double _passwordStrength5(int inputLength) {
if (inputLength < 6) {
return 0;
} else {
return (inputLength - 5) / 15 * 0.2;
}
}
bool _isValidateInput0(String input) {
RegExp regExp = RegExp(r"^[a-z0-9]{4,15}$");
return regExp.hasMatch(input);
}
bool _isValidateInput1_1(String input) {
return input.length >= 6 && input.length <= 20;
}
bool _isValidateInput1_2(String input) {
RegExp regExp = RegExp(r'^[a-zA-Z0-9!@#$]+$');
return regExp.hasMatch(input);
}
bool _isValidateInput1_3(String input) {
bool isConsecutiveLetter = containsConsecutiveLetters(input);
bool isConsecutiveNumber = containsConsecutiveNumbers(input);
return !isConsecutiveLetter && !isConsecutiveNumber;
}
@override
void initState() {
super.initState();
focusNodes = List.generate(8, (index) => FocusNode());
textEditingControllers =
List.generate(8, (index) => TextEditingController());
textEditingControllers[0].addListener(_validateInput0);
textEditingControllers[1].addListener(_validateInput1);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
popupList.clear();
popupList
.add("${AppLocalizations.of(context)?.get(StringKey.zhChina)}(+86)");
popupList
.add("${AppLocalizations.of(context)?.get(StringKey.ynVietnam)}(+84)");
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
width: double.infinity,
height: MediaQuery.of(context).size.height,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/loginBg.png"),
fit: BoxFit.cover),
),
child: Stack(children: <Widget>[
Positioned(
left: 0,
right: 0,
top: 692.h,
child: Container(
color: Colors.white,
child: Column(
verticalDirection: VerticalDirection.up,
children: [
SizedBox(height: 50.h),
goToRegisterAndConnectServiceWidget(),
SizedBox(height: 7.h),
registerWidget(),
],
),
)),
Positioned(
left: 0,
right: 0,
top: 274.h,
child: Container(
width: double.infinity,
// height: 541.h,
height: 418.h,
decoration: BoxDecoration(
color: AppColors.colorFF8EB5FA,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15.w),
topRight: Radius.circular(15.w))),
child: Stack(
children: <Widget>[
registerTypeWidget(),
Container(
margin: EdgeInsets.only(top: 44.h),
child: Stack(
children: [
accountRegisterWidget(),
telephoneRegisterWidget()
],
))
],
),
)),
]),
),
);
}
@override
void dispose() {
super.dispose();
for (var element in focusNodes) {
element.dispose();
}
for (var element in textEditingControllers) {
element.dispose();
}
_timer?.cancel();
_countDownTimer.cancel();
}
Container createTermsAndPrivacyWidget() {
return Container(
width: double.infinity,
height: 18.h,
margin: EdgeInsets.only(left: 35.w, top: 8.h),
child: Row(
children: [
CheckBoxRounded(
onTap: (value) {
setState(() {
termsSelected = value!;
});
},
size: 16.w,
borderWidth: 0,
checkedWidget:
SvgPicture.asset("assets/images/termsSelected.svg"),
isChecked: termsSelected,
uncheckedWidget:
SvgPicture.asset("assets/images/termsUnselected.svg"),
),
SizedBox(width: 4.w),
GestureDetector(
onTap: () {
setState(() {
termsSelected = !termsSelected;
});
},
child: Text(
AppLocalizations.of(context)
?.get(StringKey.readAndAgreeTerms1) ??
"I have read and agree to the ",
style: TextStyle(
fontSize: 12.sp, color: AppColors.colorFF626F86))),
Text(
AppLocalizations.of(context)
?.get(StringKey.readAndAgreeTerms2) ??
"Terms and Privacy Policy.",
style:
TextStyle(fontSize: 12.sp, color: AppColors.colorFF1D6BF5)),
],
));
}
Visibility telephoneRegisterWidget() {
return Visibility(
visible: isRightSelected ? true : false,
child: Container(
width: double.infinity,
height: double.infinity,
color: Colors.white,
child: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
height: 45.h,
margin: EdgeInsets.only(left: 35.w, right: 35.w, top: 26.h),
decoration: BoxDecoration(
color: currentFocusIndex == 4
? Colors.white
: AppColors.color1A9AB0D6,
border: Border.all(
color: input4Error
? AppColors.colorFFFF3333
: AppColors.colorFFDCDFE4,
width: 1.w),
borderRadius: BorderRadius.all(Radius.circular(8.w))),
child: createDropDownMenu(context),
),
Visibility(
visible: input4Error,
child: Container(
width: double.infinity,
height: 31.h,
margin: EdgeInsets.only(left: 35.w, right: 35.w),
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context)
?.get(StringKey.existingMobileNumber) ??
"The mobile number already exists.",
style: TextStyle(
fontSize: 12.sp,
color: AppColors.colorFFFF3333)),
)),
Container(
width: double.infinity,
height: 45.h,
margin: EdgeInsets.only(
left: 35.w, right: 35.w, top: input4Error ? 0 : 8.h),
child: TextField(
keyboardType: TextInputType.number,
// 弹出数字键盘
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly // 仅接受数字
],
controller: textEditingControllers[5],
onTap: () {
requestFocus(5);
},
style: TextStyle(
color: AppColors.colorFF252B34, fontSize: 14.sp),
maxLines: 1,
focusNode: focusNodes[5],
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 0),
isCollapsed: false,
hintText: AppLocalizations.of(context)
?.get(StringKey.enterTheVerificationCode),
hintStyle: TextStyle(
color: AppColors.colorFF8590A2, fontSize: 14.sp),
prefixIcon: Padding(
padding: EdgeInsets.only(top: 13.h, bottom: 13.h),
child: SvgPicture.asset(
"assets/images/telephoneVerifyCode.svg")),
suffixIcon: _seconds != 0 && _seconds != 60
? Padding(
padding: EdgeInsets.only(
top: 7.5.h, bottom: 7.5.h, right: 7.5.w),
child: SizedBox(
width: 33.w,
child: Center(
child: Text(
"${_seconds}s",
style: TextStyle(
color: AppColors.colorFF1D6BF5,
fontSize: 14.sp),
),
),
),
)
: Padding(
padding: EdgeInsets.only(
top: 7.5.h, bottom: 7.5.h, right: 7.5.w),
child: GestureDetector(
onTap: () {
startCountDownTimer();
},
child: Container(
padding: EdgeInsets.only(
left: 5.w, right: 5.w),
width: 83.w,
alignment: Alignment.centerRight,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(8.w))),
child: Center(
child: Text(
AppLocalizations?.of(context)?.get(
StringKey
.getTheVerificationCode) ??
"Get verification code",
style: TextStyle(
fontSize: 14.sp,
color: AppColors.colorFF3461AD),
),
)),
),
),
// suffixIconConstraints: BoxConstraints(minWidth: 14.w,maxWidth: 14.w),
filled: true,
fillColor: currentFocusIndex == 5
? Colors.white
: AppColors.color1A9AB0D6,
enabledBorder: input5Error
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333, width: 1.w),
)
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w)),
focusedBorder: input5Error
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333, width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w)),
),
// )
),
),
Visibility(
visible: input5Error,
child: Container(
width: double.infinity,
height: 31.h,
margin: EdgeInsets.only(left: 35.w, right: 35.w),
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context)
?.get(StringKey.invalidVerificationCode) ??
"Invalid verification code.",
style: TextStyle(
fontSize: 12.sp,
color: AppColors.colorFFFF3333)),
)),
createInviteCodeWidget(),
createInvalidInviteCodeWidget(),
createTermsAndPrivacyWidget(),
],
),
)));
}
Visibility accountRegisterWidget() {
return Visibility(
visible: isRightSelected ? false : true,
child: Container(
width: double.infinity,
height: double.infinity,
color: Colors.white,
child: SingleChildScrollView(
child: Column(
children: [
// Expanded(child:
Container(
margin:
EdgeInsets.only(left: 35.w, right: 35.w, top: 26.h),
height: 45.h,
child: TextField(
controller: textEditingControllers[0],
onTap: () {
requestFocus(0);
},
style: TextStyle(
color: AppColors.colorFF252B34, fontSize: 14.sp),
maxLines: 1,
focusNode: focusNodes[0],
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 0),
isCollapsed: false,
hintText: AppLocalizations.of(context)
?.get(StringKey.accountRegisterHint),
hintStyle: TextStyle(
color: AppColors.colorFF8590A2, fontSize: 14.sp),
prefixIcon: Padding(
padding: EdgeInsets.only(top: 13.h, bottom: 13.h),
child: SvgPicture.asset(
"assets/images/userPrefixIcon.svg")),
suffixIcon: input0Error
? null
: Padding(
padding: EdgeInsets.only(
top: 14.5.h, bottom: 14.5.h),
child: SvgPicture.asset(
"assets/images/userSuffixIcon.svg",
),
),
// suffixIconConstraints: BoxConstraints(minWidth: 14.w,maxWidth: 14.w),
filled: true,
fillColor: currentFocusIndex == 0
? Colors.white
: AppColors.color1A9AB0D6,
enabledBorder: input0Error && isInit0
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333,
width: 1.w),
)
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w)),
focusedBorder: input0Error && isInit0
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333,
width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w)),
),
// )
)),
Visibility(
visible: input0Error && isInit0,
child: Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(left: 35.w, right: 35.w),
child: Text(
AppLocalizations.of(context)
?.get(StringKey.accountRegisterNumberRuler) ??
"The username is composed of lowercase English letters and numbers.It should be between 4 and 15 characters long.Special characters are not allowed.Spaces are not allowed.",
style: TextStyle(
color: AppColors.colorFFFF3333, fontSize: 12.sp),
),
)),
Container(
margin:
EdgeInsets.only(left: 35.w, right: 35.w, top: 8.h),
height: 45.h,
child: TextField(
onChanged: (value) {
setState(() {
password = value;
});
},
controller: textEditingControllers[1],
onTap: () {
requestFocus(1);
},
obscureText: passwordIsObscure.value,
inputFormatters: [LengthLimitingTextInputFormatter(20)],
style: TextStyle(
color: AppColors.colorFF252B34, fontSize: 14.sp),
maxLines: 1,
focusNode: focusNodes[1],
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 0),
hintText: AppLocalizations.of(context)
?.get(StringKey.enterPassword),
hintStyle: TextStyle(
color: AppColors.colorFF8590A2, fontSize: 14.sp),
prefixIcon: Padding(
padding: EdgeInsets.only(top: 13.h, bottom: 13.h),
child: SvgPicture.asset(
"assets/images/passwordPrefixIcon.svg")),
suffixIcon: ValueListenableBuilder<bool>(
valueListenable: passwordIsObscure,
builder: (context, value, child) {
return GestureDetector(
onTap: () {
setState(() {
passwordIsObscure.value =
!passwordIsObscure.value;
});
},
child: passwordIsObscure.value
? Padding(
padding: EdgeInsets.only(
top: 14.5.h, bottom: 14.5.h),
child: SvgPicture.asset(
"assets/images/passwordIsObscure.svg",
),
)
: Padding(
padding: EdgeInsets.only(
top: 14.5.h, bottom: 14.5.h),
child: SvgPicture.asset(
"assets/images/passwordIsNotObscure.svg",
),
));
},
),
filled: true,
fillColor: currentFocusIndex == 1
? Colors.white
: AppColors.color1A9AB0D6,
enabledBorder: (input1Error && isInit1) ||
(password != againPassword)
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333,
width: 1.w),
)
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w)),
focusedBorder: (input1Error && isInit1) ||
(againPassword != password &&
currentFocusIndex == 2)
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333,
width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w)),
),
)),
Visibility(
visible: currentFocusIndex == 1,
child: Container(
margin:
EdgeInsets.only(left: 35.w, top: 8.h, right: 35.w),
child: Column(
children: [
SizedBox(
width: double.infinity,
height: 7.h,
child: ClipRect(
child: LinearProgressIndicator(
borderRadius:
BorderRadius.all(Radius.circular(18.w)),
value: ((passwordStrength1 ? 0.2 : 0) +
(passwordStrength2 ? 0.2 : 0) +
(passwordStrength3 ? 0.2 : 0) +
(passwordStrength4 ? 0.2 : 0) +
passwordStrength5) /
1.0,
backgroundColor: AppColors.colorFFEEEEEE,
color: AppColors.colorFFFFB500,
),
),
),
SizedBox(height: 5.h),
passwordErrorHintWidget(
!input1Error1,
AppLocalizations.of(context)?.get(StringKey
.accountRegisterPasswordRuler1) ??
"6 - 20 characters"),
SizedBox(height: 5.h),
passwordErrorHintWidget(
!input1Error2,
AppLocalizations.of(context)?.get(StringKey
.accountRegisterPasswordRuler2) ??
"Consists of uppercase and lowercase letters or numbers (allowing symbols !@#\$, not allowing spaces)"),
SizedBox(height: 5.h),
passwordErrorHintWidget(
!input1Error3,
AppLocalizations.of(context)?.get(StringKey
.accountRegisterPasswordRuler3) ??
"Cannot have 3 or more consecutive letters or numbers (e.g., abc, 123)"),
],
),
)),
Container(
margin:
EdgeInsets.only(left: 35.w, right: 35.w, top: 8.h),
height: 45.h,
child: TextField(
onChanged: (value) {
setState(() {
againPassword = value;
});
},
obscureText: passwordAgainObscure,
style: TextStyle(
color: AppColors.colorFF252B34, fontSize: 14.sp),
controller: textEditingControllers[2],
onTap: () {
requestFocus(2);
},
maxLines: 1,
focusNode: focusNodes[2],
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 0),
hintText: AppLocalizations.of(context)
?.get(StringKey.reEnterPassword),
hintStyle: TextStyle(
color: AppColors.colorFF8590A2, fontSize: 14.sp),
prefixIcon: Padding(
padding: EdgeInsets.only(top: 13.h, bottom: 13.h),
child: SvgPicture.asset(
"assets/images/passwordPrefixIcon.svg")),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
passwordAgainObscure = !passwordAgainObscure;
});
},
child: passwordAgainObscure
? Padding(
padding: EdgeInsets.only(
top: 14.5.h, bottom: 14.5.h),
child: SvgPicture.asset(
"assets/images/passwordIsObscure.svg",
),
)
: Padding(
padding: EdgeInsets.only(
top: 14.5.h, bottom: 14.5.h),
child: SvgPicture.asset(
"assets/images/passwordIsNotObscure.svg",
),
)),
filled: true,
fillColor: currentFocusIndex == 2
? Colors.white
: AppColors.color1A9AB0D6,
enabledBorder: currentFocusIndex != 2
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w))
: (againPassword == password)
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333,
width: 1.w)),
focusedBorder: currentFocusIndex != 2
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w))
: (againPassword == password)
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4,
width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333,
width: 1.w)),
),
)),
Visibility(
visible:
password != againPassword && currentFocusIndex == 2,
child: Container(
alignment: Alignment.centerLeft,
margin:
EdgeInsets.only(left: 35.w, right: 35.w, top: 8.h),
child: Text(
AppLocalizations.of(context)
?.get(StringKey.passwordsNotMatch) ??
"The passwords entered do not match.",
style: TextStyle(
color: AppColors.colorFFFF3333, fontSize: 12.sp),
),
)),
createInviteCodeWidget(),
createInvalidInviteCodeWidget(),
createTermsAndPrivacyWidget(),
],
),
)));
}
SizedBox registerTypeWidget() {
return SizedBox(
height: 45.h,
width: double.infinity,
child: Row(
children: [
Expanded(
child: InkWell(
onTap: () {
updateSelection(false);
},
child: Container(
decoration: BoxDecoration(
color: isRightSelected == true
? Colors.transparent
: Colors.white,
borderRadius: isRightSelected == true
? const BorderRadius.all(Radius.circular(0))
: BorderRadius.only(
topLeft: Radius.circular(15.w),
topRight: Radius.circular(15.w)),
),
child: Center(
child: Text(
AppLocalizations.of(context)
?.get(StringKey.accountRegister) ??
"AAAA",
style: TextStyle(
fontSize: 18.sp,
color: isRightSelected == false
? AppColors.colorFF3461AD
: Colors.white)),
)),
),
),
Expanded(
child: InkWell(
onTap: () {
updateSelection(true);
},
child: Container(
decoration: BoxDecoration(
color: isRightSelected == false
? Colors.transparent
: Colors.white,
borderRadius: isRightSelected == false
? const BorderRadius.all(Radius.circular(0))
: BorderRadius.only(
topLeft: Radius.circular(15.w),
topRight: Radius.circular(15.w)),
),
child: Center(
child: Text(
AppLocalizations.of(context)
?.get(StringKey.telephoneRegister) ??
"AAAA",
style: TextStyle(
fontSize: 18.sp,
color: isRightSelected == true
? AppColors.colorFF3461AD
: Colors.white)),
),
)),
),
],
),
);
}
ElevatedButton registerWidget() {
return ElevatedButton(
onPressed: !input0Error &&
!input1Error &&
!input3Error &&
(password == againPassword)
? () {}
: null,
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.w))),
minimumSize: MaterialStateProperty.all<Size>(Size(305.w, 48.h)),
backgroundColor: !input0Error &&
!input1Error &&
!input3Error &&
(password == againPassword)
? MaterialStateProperty.all<Color>(AppColors.colorFF1D6BF5)
: MaterialStateProperty.all<Color>(AppColors.color801D6BF5),
),
child: Text(
AppLocalizations.of(context)?.get(StringKey.register) ?? "Register",
style: TextStyle(color: Colors.white, fontSize: 16.sp),
),
);
}
Row goToRegisterAndConnectServiceWidget() {
return Row(
children: [
Container(
margin: EdgeInsets.only(left: 74.w),
child: (Text(
AppLocalizations.of(context)?.get(StringKey.goToLogin) ??
"Already have an account? Go to login.",
style: TextStyle(color: AppColors.colorFF3461AD, fontSize: 14.sp),
)),
),
Container(
margin: EdgeInsets.only(left: 60.w),
child: (Text(
AppLocalizations.of(context)
?.get(StringKey.contactCustomerService) ??
"Contact customer service.",
style: TextStyle(color: AppColors.colorFF3461AD, fontSize: 14.sp),
)),
)
],
);
}
Row passwordErrorHintWidget(bool isSelected, String tips) {
return Row(
children: [
CheckBoxRounded(
onTap: (value) {
setState(() {
isSelected = value!;
});
},
size: 16.w,
borderWidth: 0,
checkedWidget: SvgPicture.asset("assets/images/termsSelected.svg"),
isChecked: isSelected,
uncheckedWidget:
SvgPicture.asset("assets/images/termsUnselected.svg"),
),
SizedBox(width: 4.w),
Flexible(
child: Text(tips,
maxLines: null,
style:
TextStyle(fontSize: 12.sp, color: AppColors.color801D6BF5)))
],
);
}
// 判断段三个字符串是否相邻
bool containsConsecutiveLetters(String input) {
for (var i = 0; i < input.length - 2; i++) {
var first = input.codeUnitAt(i);
var second = input.codeUnitAt(i + 1);
var third = input.codeUnitAt(i + 2);
if (first + 1 == second && second + 1 == third) {
return true;
}
}
return false;
}
// 判断三个相邻数字是否顺序连续
bool containsConsecutiveNumbers(String input) {
for (var i = 0; i < input.length - 2; i++) {
var first = int.tryParse(input[i]);
var second = int.tryParse(input[i + 1]);
var third = int.tryParse(input[i + 2]);
if (first != null && second != null && third != null) {
if (first + 1 == second && second + 1 == third) {
return true;
}
}
}
return false;
}
void _inviteCodeOnChanged(String value) {
setState(() {
inputText3 = value;
});
_timer?.cancel();
_timer = Timer(_inputDuration, () {
//发起网络请求
print("发起网络请求${value}");
});
}
Builder createDropDownMenu(BuildContext context) {
return Builder(builder: (context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 14.w),
SvgPicture.asset("assets/images/telephone.svg"),
SizedBox(width: 3.w),
GestureDetector(
onTap: () {
setState(() {
isShowPopup = true;
});
SmartDialog.showAttach(
tag: "countryTag",
backDismiss: true,
onDismiss: () {
setState(() {
isShowPopup = false;
});
},
// targetBuilder: ,该属性设置偏移
maskColor: Colors.transparent,
targetContext: context,
alignment: Alignment.bottomCenter,
builder: (context) {
return SizedBox(
width: 305.w,
child: ListView.builder(
padding: EdgeInsets.zero,
itemExtent: 44.h,
shrinkWrap: true,
itemCount: popupList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
selectedCountryIndex = index;
});
SmartDialog.dismiss(
status: SmartStatus.attach,
tag: "countryTag");
},
child: Container(
decoration: BoxDecoration(
color: selectedCountryIndex == index
? AppColors.colorFFD7E5FF
: AppColors.colorFFF5F8FB,
borderRadius: index ==
popupList.length - 1
? BorderRadius.only(
bottomLeft: Radius.circular(8.w),
bottomRight: Radius.circular(8.w))
: null),
child: Container(
margin: EdgeInsets.only(left: 16.w),
alignment: Alignment.centerLeft,
child: Text(popupList[index],
style: TextStyle(
fontSize: 14.sp,
color: selectedCountryIndex == index
? AppColors.colorFF1D6BF5
: AppColors.colorFF626F86)),
),
));
}),
);
});
},
child: Row(
children: [
Text(getSelectedText(selectedCountryIndex),
style: TextStyle(
color: AppColors.colorFF252B34, fontSize: 14.sp)),
SizedBox(width: 3.w),
isShowPopup
? SvgPicture.asset("assets/images/downMenuTipUp.svg")
: SvgPicture.asset("assets/images/downMenuTipDown.svg"),
],
),
),
SizedBox(width: 10.w),
Flexible(
flex: 1,
child: Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.centerLeft,
child: TextField(
keyboardType: TextInputType.number,
// 弹出数字键盘
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly // 仅接受数字
],
controller: textEditingControllers[4],
onTap: () {
requestFocus(4);
},
maxLines: 1,
focusNode: focusNodes[4],
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 0),
hintText: isShowPopup
? AppLocalizations.of(context)
?.get(StringKey.selectACountry)
: AppLocalizations.of(context)
?.get(StringKey.enterYourPhoneNumber),
hintStyle: TextStyle(
color: AppColors.colorFF8590A2, fontSize: 14.sp),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent, width: 1.w)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent, width: 1.w))),
style: TextStyle(
fontSize: 14.sp,
color: AppColors.colorFF252B34,
))),
),
],
);
});
}
String getSelectedText(int selectedCountryIndex) {
String tempSelected = "";
switch (selectedCountryIndex) {
case 0:
tempSelected = "+86";
break;
case 1:
tempSelected = "+84";
break;
}
return tempSelected;
}
void startCountDownTimer() {
_countDownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
_seconds--;
});
if (_seconds == 0) {
_countDownTimer.cancel();
}
});
}
Container createInviteCodeWidget() {
return Container(
margin: EdgeInsets.only(left: 35.w, right: 35.w, top: 8.h),
height: 45.h,
child: TextField(
onChanged: _inviteCodeOnChanged,
controller: textEditingControllers[3],
onTap: () {
requestFocus(3);
},
style: TextStyle(color: AppColors.colorFF252B34, fontSize: 14.sp),
maxLines: 1,
focusNode: focusNodes[3],
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 0),
hintText: AppLocalizations.of(context)
?.get(StringKey.accountRegisterHint),
hintStyle:
TextStyle(color: AppColors.colorFF8590A2, fontSize: 14.sp),
prefixIcon: Padding(
padding: EdgeInsets.only(top: 13.h, bottom: 13.h),
child:
SvgPicture.asset("assets/images/inviteCodePrefixIcon.svg")),
filled: true,
fillColor:
currentFocusIndex == 3 ? Colors.white : AppColors.color1A9AB0D6,
enabledBorder: inputText3.isEmpty
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide:
BorderSide(color: AppColors.colorFFDCDFE4, width: 1.w))
: (input3Error
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333, width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4, width: 1.w))),
focusedBorder: inputText3.isEmpty
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide:
BorderSide(color: AppColors.colorFFDCDFE4, width: 1.w))
: (input3Error
? OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFFF3333, width: 1.w))
: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.w),
borderSide: BorderSide(
color: AppColors.colorFFDCDFE4, width: 1.w))),
),
));
}
Visibility createInvalidInviteCodeWidget() {
return Visibility(
visible: input3Error,
child: Container(
width: double.infinity,
margin: EdgeInsets.only(left: 35.w, top: 8.h),
child: Text(
AppLocalizations.of(context)
?.get(StringKey.invalidInvitationCode) ??
"Invalid invitation code.",
textAlign: TextAlign.left,
style: TextStyle(color: AppColors.colorFFFF3333, fontSize: 12.sp),
)));
}
}