You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者황희윤

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 14:03:20