Flutter如何使用switch case结合Provider实现可复用表单配置
Flutter 登录注册表单复用实现方案
通过switch case统一配置不同输入字段的属性,只需要维护一个TextFormField组件即可覆盖用户名、密码、邮箱三种输入场景。
1. 修改LoginSignupData状态类
在原有状态管理逻辑中补充字段配置匹配、统一赋值的方法,所有和字段属性相关的逻辑都收敛到状态类中统一维护:
class LoginSignupData extends ChangeNotifier{ final authentication = FirebaseAuth.instance; bool isSignup = true; final formKey = GlobalKey<FormState>(); String userName = ''; String userEmail = ''; String userPassword = ''; changeBool(status){ isSignup = status; notifyListeners(); } tryValidation() { final isValid = formKey.currentState!.validate(); if (isValid) { formKey.currentState!.save(); notifyListeners(); } } // 匹配不同字段的校验警告文本 String getWarningText(String fieldType) { switch(fieldType) { case 'username': return 'Please enter at least 4 characters'; case 'password': return 'Password must be at least 7 characters long.'; case 'email': return 'Please enter a valid email address.'; default: return ''; } } // 匹配不同字段的前缀图标 IconData getPrefixIcon(String fieldType) { switch(fieldType) { case 'username': return Icons.account_circle; case 'password': return Icons.lock; case 'email': return Icons.email; default: return Icons.text_fields; } } // 匹配不同字段的提示文本 String getHintText(String fieldType) { switch(fieldType) { case 'username': return 'username'; case 'password': return 'password'; case 'email': return 'email'; default: return ''; } } // 统一更新对应字段的输入值 void updateFieldValue(String fieldType, String value) { switch(fieldType) { case 'username': userName = value; break; case 'password': userPassword = value; break; case 'email': userEmail = value; break; } notifyListeners(); } }
2. 重构通用输入组件
把原有写死的密码相关配置、校验、赋值逻辑全部替换为调用状态类的匹配方法,实现组件全复用:
class LoginSignupTextFormField extends StatelessWidget { const LoginSignupTextFormField({Key? key, required this.valueKeyNumb, required this.textValue}) : super(key: key); final int valueKeyNumb; // 传入字段类型,可选值:username、password、email final String textValue; @override Widget build(BuildContext context) { final formData = context.watch<LoginSignupData>(); return TextFormField( // 仅密码字段密文显示 obscureText: textValue == 'password', key: ValueKey(valueKeyNumb), validator: (value) { // 空值统一返回对应提示 if (value == null || value.isEmpty) { return formData.getWarningText(textValue); } // 不同字段走对应校验规则 switch(textValue) { case 'username': if (value.length < 4) return formData.getWarningText(textValue); break; case 'password': if (value.length < 7) return formData.getWarningText(textValue); break; case 'email': // 邮箱格式正则校验 final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); if (!emailRegex.hasMatch(value)) return formData.getWarningText(textValue); break; } return null; }, onSaved: (value) { if (value != null) formData.updateFieldValue(textValue, value); }, onChanged: (value) { formData.updateFieldValue(textValue, value); }, decoration: InputDecoration( prefixIcon: Icon( formData.getPrefixIcon(textValue), color: Colors.red, ), enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.blueGrey), borderRadius: BorderRadius.all(Radius.circular(35.0)), ), focusedBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), borderRadius: BorderRadius.all(Radius.circular(35.0)), ), hintText: formData.getHintText(textValue), hintStyle: const TextStyle(fontSize: 14, color: Colors.red), contentPadding: const EdgeInsets.all(10) ), ); } }
组件调用方式
在表单中传入不同的textValue参数即可生成对应输入框,无需重复编写组件代码:
// 用户名输入框 LoginSignupTextFormField(valueKeyNumb: 1, textValue: 'username'), const SizedBox(height: 16), // 邮箱输入框 LoginSignupTextFormField(valueKeyNumb: 2, textValue: 'email'), const SizedBox(height: 16), // 密码输入框 LoginSignupTextFormField(valueKeyNumb: 3, textValue: 'password'),
内容的提问来源于stack exchange,提问作者황희윤
相关产品推荐
相关产品推荐

