Flutter for OpenHarmony 实战 表单处理与验证完整指南

【Flutter实战】Flutter表单处理与验证完整指南

### 文章目录

  • [【Flutter实战】Flutter表单处理与验证完整指南](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [@[toc]](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [前言](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [一、表单基础组件](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [1.1 TextFormField基础](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [1.2 表单字段类型](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [二、表单验证封装](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [2.1 验证器封装](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [2.2 使用验证器](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [三、表单美化技巧](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [3.1 自定义边框](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [3.2 表单字段组件封装](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [四、复杂表单处理](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [4.1 多步骤表单](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [4.2 动态表单](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
  • [总结](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)

前言

表单处理看似简单,实则有很多细节。验证规则、错误提示、提交逻辑,每一项都需要仔细考虑。

我做过的表单从简单的登录注册,到复杂的多步骤向导,积累了不少经验。这篇文章我想分享表单处理的实践技巧。


一、表单基础组件

1.1 TextFormField基础

dart 复制代码
class BasicForm extends StatefulWidget {
  @override
  State<BasicForm> createState() => _BasicFormState();
}

class _BasicFormState extends State<BasicForm> {
  final _formKey = GlobalKey<FormState>();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();

  @override
  void dispose() {
    _nameController.dispose();
    _emailController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
            controller: _nameController,
            decoration: InputDecoration(
              labelText: '姓名',
              prefixIcon: Icon(Icons.person),
              border: OutlineInputBorder(),
            ),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return '请输入姓名';
              }
              return null;
            },
          ),
          SizedBox(height: 16),
          TextFormField(
            controller: _emailController,
            decoration: InputDecoration(
              labelText: '邮箱',
              prefixIcon: Icon(Icons.email),
              border: OutlineInputBorder(),
            ),
            keyboardType: TextInputType.emailAddress,
            validator: (value) {
              if (value == null || value.isEmpty) {
                return '请输入邮箱';
              }
              if (!value.contains('@')) {
                return '请输入有效的邮箱地址';
              }
              return null;
            },
          ),
          SizedBox(height: 24),
          ElevatedButton(
            onPressed: _submitForm,
            child: Text('提交'),
          ),
        ],
      ),
    );
  }

  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      print('姓名: ${_nameController.text}');
      print('邮箱: ${_emailController.text}');
    }
  }
}

1.2 表单字段类型

dart 复制代码
// 密码输入
TextFormField(
  obscureText: true,
  decoration: InputDecoration(
    labelText: '密码',
    suffixIcon: Icon(Icons.visibility),
  ),
)

// 多行输入
TextFormField(
  maxLines: 5,
  decoration: InputDecoration(
    labelText: '描述',
  ),
)

// 数字输入
TextFormField(
  keyboardType: TextInputType.number,
  decoration: InputDecoration(labelText: '年龄'),
)

二、表单验证封装

2.1 验证器封装

dart 复制代码
class Validators {
  static final RegExp _emailRegExp = RegExp(
    r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
  );

  static final RegExp _phoneRegExp = RegExp(
    r'^1[3-9]\d{9}$',
  );

  static String? required(String? value, [String message = '此项不能为空']) {
    if (value == null || value.isEmpty) {
      return message;
    }
    return null;
  }

  static String? email(String? value) {
    if (value == null || value.isEmpty) {
      return '请输入邮箱';
    }
    if (!_emailRegExp.hasMatch(value)) {
      return '请输入有效的邮箱地址';
    }
    return null;
  }

  static String? phone(String? value) {
    if (value == null || value.isEmpty) {
      return '请输入手机号';
    }
    if (!_phoneRegExp.hasMatch(value)) {
      return '请输入有效的手机号';
    }
    return null;
  }

  static String? length(String? value, int min, int max) {
    if (value == null || value.isEmpty) {
      return '请输入内容';
    }
    if (value.length < min || value.length > max) {
      return '长度应在$min到$max之间';
    }
    return null;
  }
}

2.2 使用验证器

dart 复制代码
TextFormField(
  decoration: InputDecoration(labelText: '邮箱'),
  validator: Validators.email,
)

三、表单美化技巧

3.1 自定义边框

dart 复制代码
TextFormField(
  decoration: InputDecoration(
    labelText: '用户名',
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(8),
    ),
    focusedBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(8),
      borderSide: BorderSide(color: Colors.blue, width: 2),
    ),
    errorBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(8),
      borderSide: BorderSide(color: Colors.red),
    ),
  ),
)

3.2 表单字段组件封装

dart 复制代码
class AppTextField extends StatelessWidget {
  final String label;
  final IconData? icon;
  final bool obscureText;
  final String? Function(String?)? validator;
  final TextEditingController? controller;

  const AppTextField({
    super.key,
    required this.label,
    this.icon,
    this.obscureText = false,
    this.validator,
    this.controller,
  });

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: controller,
      obscureText: obscureText,
      validator: validator,
      decoration: InputDecoration(
        labelText: label,
        prefixIcon: icon != null ? Icon(icon) : null,
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    );
  }
}

四、复杂表单处理

4.1 多步骤表单

dart 复制代码
class MultiStepForm extends StatefulWidget {
  @override
  State<MultiStepForm> createState() => _MultiStepFormState();
}

class _MultiStepFormState extends State<MultiStepForm> {
  int _currentStep = 0;
  final _formKeys = [
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
  ];

  List<Step> get _steps => [
    Step(
      title: Text('基本信息'),
      content: Form(
        key: _formKeys[0],
        child: Column(
          children: [
            AppTextField(label: '姓名', validator: Validators.required),
            SizedBox(height: 16),
            AppTextField(label: '邮箱', validator: Validators.email),
          ],
        ),
      ),
      isActive: _currentStep >= 0,
    ),
    Step(
      title: Text('详细信息'),
      content: Form(
        key: _formKeys[1],
        child: Column(
          children: [
            AppTextField(label: '电话', validator: Validators.phone),
          ],
        ),
      ),
      isActive: _currentStep >= 1,
    ),
    Step(
      title: Text('确认'),
      content: Form(
        key: _formKeys[2],
        child: Column(
          children: [
            Text('请确认信息'),
          ],
        ),
      ),
      isActive: _currentStep >= 2,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Stepper(
      currentStep: _currentStep,
      steps: _steps,
      onStepContinue: () {
        if (_currentStep < _steps.length - 1) {
          if (_formKeys[_currentStep].currentState!.validate()) {
            setState(() => _currentStep++);
          }
        }
      },
      onStepCancel: () {
        if (_currentStep > 0) {
          setState(() => _currentStep--);
        }
      },
    );
  }
}

4.2 动态表单

dart 复制代码
class DynamicForm extends StatefulWidget {
  @override
  State<DynamicForm> createState() => _DynamicFormState();
}

class _DynamicFormState extends State<DynamicForm> {
  final List<TextEditingController> _controllers = [];

  void _addItem() {
    setState(() {
      _controllers.add(TextEditingController());
    });
  }

  void _removeItem(int index) {
    setState(() {
      _controllers[index].dispose();
      _controllers.removeAt(index);
    });
  }

  @override
  void dispose() {
    for (var controller in _controllers) {
      controller.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ..._controllers.asMap().entries.map((entry) {
          final index = entry.key;
          final controller = entry.value;
          return Padding(
            padding: const EdgeInsets.only(bottom: 16),
            child: Row(
              children: [
                Expanded(
                  child: TextFormField(
                    controller: controller,
                    decoration: InputDecoration(labelText: '项目 ${index + 1}'),
                  ),
                ),
                IconButton(
                  icon: Icon(Icons.delete),
                  onPressed: () => _removeItem(index),
                ),
              ],
            ),
          );
        }),
        ElevatedButton.icon(
          onPressed: _addItem,
          icon: Icon(Icons.add),
          label: Text('添加项目'),
        ),
      ],
    );
  }
}

总结

表单处理需要注意细节。

核心要点:

  1. 使用Form和GlobalKey管理表单
  2. 封装验证器提高复用性
  3. 提供清晰的错误提示
  4. 美化表单提升体验
  5. 处理好提交状态

最佳实践:

  • 实时验证反馈
  • 防重复提交
  • 保存草稿功能
  • 自动填充支持
  • 无障碍支持

好的表单设计让用户输入更顺畅。

欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区

相关推荐
leiming62 小时前
FreeRTOS 的任务与 Linux
java·开发语言
weixin_395448912 小时前
main.c_cursor_0130
前端·网络·算法
2601_949975082 小时前
flutter_for_openharmony城市井盖地图app实战+附近井盖实现
android·flutter
倾云鹤2 小时前
通用Digest认证
android·digest
向哆哆2 小时前
构建 Flutter × OpenHarmony 跨端健康档案管理顶部横幅的实现与解析
flutter·开源·鸿蒙·openharmony
C澒2 小时前
SGW 接入层运维实战:配置查看 + 监控分析 + 日志排查
前端·安全·运维开发
田野追逐星光2 小时前
STL的容器vector的模拟实现
开发语言·c++
2601_949975792 小时前
Flutter for OpenHarmony艺考真题题库+成绩对比实现
flutter
向哆哆2 小时前
构建跨端健康档案管理系统:Flutter × OpenHarmony 实战解析
flutter·开源·鸿蒙·openharmony·开源鸿蒙