flutter 实现表单的封装包含下拉框和输入框

一、表单封装组件实现效果

在这里插入图片描述

//表单组件
Widget buildFormWidget(List<InputModel> formList,
    {required GlobalKey<FormState> formKey}) {
  return Form(
      key: formKey,
      child: Column(
        children: formList.map((item) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  item.isRequired
                      ? Icon(Icons.star,
                          size: 10,
                          color: Theme.of(Get.context!).colorScheme.error)
                      : SizedBox(),
                  Text(
                    item.label,
                    style:
                        Theme.of(Get.context!).inputDecorationTheme.labelStyle,
                  )
                ],
              ),
              SizedBox(
                height: 16,
              ),
              GestureDetector(
                onTap: item.type == 'select'
                    ? () {
                        showBottomSheet(item.bottomSheetList!, item.label,
                            selectProp: item.selectProp,
                            selectController: item.selectController,
                            controller: item.controller);
                      }
                    : null,
                child: TextFormField(
                  controller: item.controller,
                  enabled: item.type == 'text',
                  keyboardType: item.keyboardType,
                  validator: (value) {
                    // 添加表单验证
                    if (item.isRequired && (value == null || value.isEmpty)) {
                      return '请${item.type == 'select' ? '选择' : '输入'}${item.label}';
                    }
                    //正则表达式验证
                    if (item.pattern.isEmpty &&
                        (value == null || value.isEmpty)) {
                      RegExp regex = RegExp(item.pattern);
                      if (!regex.hasMatch(value!)) {
                        return '请输入正确的${item.label}';
                      }
                    }
                    return null;
                  },
                  decoration: InputDecoration(
                    suffixIcon: item.type == 'select'
                        ? Icon(Icons.arrow_forward_ios,
                            color: Color(0x6615171E))
                        : null,
                    focusedBorder: Theme.of(Get.context!)
                        .inputDecorationTheme
                        .focusedBorder,
                    disabledBorder: Theme.of(Get.context!)
                        .inputDecorationTheme
                        .disabledBorder,
                    enabledBorder: Theme.of(Get.context!)
                        .inputDecorationTheme
                        .enabledBorder,
                    errorBorder:
                        Theme.of(Get.context!).inputDecorationTheme.errorBorder,
                    errorStyle:
                        Theme.of(Get.context!).inputDecorationTheme.errorStyle,
                    hintText:
                        '请${item.type == 'select' ? '选择' : '输入'}${item.label}',
                    isDense: true,
                    filled: true,
                    fillColor:
                        Theme.of(Get.context!).inputDecorationTheme.fillColor,
                  ),
                ),
              ),
              SizedBox(
                height: 16,
              ),
            ],
          );
        }).toList(),
      ));
}


//bottomSheet
void showBottomSheet(List<Map<String, dynamic>> list, String title,
    {Map? selectProp,
    RxMap<String, dynamic>? selectController,
    TextEditingController? controller}) {
  showGenderPanel(
      title,
      buildCheckList(list, (item) {
        controller?.text = item[selectProp?['label']];
        Get.back();
      }, props: selectProp, selected: selectController));
}


// 底部弹出层
void showGenderPanel(String title, Widget sheetContent) {
  showModalBottomSheet(
      context: Get.context!,
      builder: (context) {
        return Container(
            height: 800,
            child: Column(
              children: [
                Container(
                    // height: 100,
                    padding: Theme.of(Get.context!).dialogTheme.actionsPadding,
                    child: Stack(
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Text(
                              title,
                              overflow: TextOverflow.ellipsis, // 显示省略号
                              style: Theme.of(Get.context!)
                                  .dialogTheme
                                  .titleTextStyle,
                            ),
                          ],
                        ),
                        Positioned(
                          right: 20,
                          // top: 14,
                          child: GestureDetector(
                            onTap: () {
                              Navigator.pop(context);
                            },
                            child: Icon(Icons.cancel_outlined,
                                color: Theme.of(Get.context!)
                                    .dialogTheme
                                    .iconColor),
                          ),
                        ),
                      ],
                    )),
                Divider(
                  height: 1,
                  // color: Theme.of(Get.context!).dividerColor,
                ),
                Container(
                  // padding: EdgeInsets.all(16),
                  child: sheetContent,
                )
              ],
            ));
      });
}


//单选列表
Widget buildCheckList(List<Map<String, dynamic>> list, Function? onChanged,
    {Map? props, RxMap<String, dynamic>? selected}) {
  props ??= {'label': 'label', 'value': 'value'};
  String label = props['label'] ?? 'label';
  String value = props['value'] ?? 'value';
  return Obx(() => Container(
      width: Get.width,
      child: Column(
        children: list.asMap().entries.map((entry) {
          int index = entry.key;
          dynamic item = entry.value;
          print('渲染');
          return Column(
            children: [
              GestureDetector(
                  onTap: () {
                    selected?.value = item;
                    if (onChanged != null) {
                      onChanged(item);
                    }
                  },
                  child: Container(
                    width: Get.width,
                    decoration: BoxDecoration(
                      color: Colors.blue.withOpacity(0),
                    ),
                    padding: const EdgeInsets.symmetric(
                        vertical: 16, horizontal: 16),
                    child: Row(
                      children: [
                        Icon(
                            (selected?.value[value] ?? '') == item[value]
                                ? Icons.check_circle
                                : Icons.circle_outlined,
                            size: 22,
                            color: (selected?.value[value] ?? '') == item[value]
                                ? Color.fromRGBO(50, 73, 223, 1)
                                : Color.fromRGBO(21, 23, 30, 0.40)),
                        SizedBox(width: 6),
                        Text(
                          item[label],
                          style: TextStyle(
                            fontSize: 16,
                          ),
                        ),
                      ],
                    ),
                  )),
              Divider(
                height: 1,
                color: index + 1 == list.length
                    ? Color.fromRGBO(128, 130, 145, 0)
                    : Color.fromRGBO(128, 130, 145, 0.20),
              ),
            ],
          );
        }).toList(),
      )));
}


二、调用方法:

 buildFormWidget(formList, formKey: formKey),

三、数据格式:


  Map<String, dynamic> controllers = {
    'phone': TextEditingController(text: '仓库1'),
    'phoneSelect': <String, dynamic>{'id': '18', 'name': '仓库1'}.obs,
    'code': TextEditingController(text: '123'),
  };
  
 formList = [
      InputModel(
          label: '入库仓库',
          isRequired: true,
          type: 'select',
          controller: controllers['phone'],
          selectController: controllers['phoneSelect'],
          bottomSheetList: bottomSheetList,
          selectProp: {'label': 'name', 'value': 'id'}),
      InputModel(
          label: '入库数量',
          isRequired: true,
          keyboardType: TextInputType.number,
          controller: controllers['code']),
    ];

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/562270.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4月21日Linux运维用户相关的添加,分组,修改权限等shell脚本开发第一天

4月21日运维用户相关的添加&#xff0c;分组&#xff0c;修改权限等shell脚本开发第一天 第一天主要实现前2个功能 ​ 主要卡在了&#xff1a; 正确的写法如下&#xff0c;注意[]中的空格&#xff0c;要求很严格&#xff01;&#xff01;&#xff01; #!/bin/bash # 先查看已…

LIUNX系统编程:文件系统

目录 1.创建文件的本质 1.1目录本身也是一个文件&#xff0c;也有他自己的inode 1.2LINUX创建文件&#xff0c;一定是在目录中创建文件。 2.重谈文件的增删查改 2.1为什目录没有写权限&#xff0c;就不能新建文件。 2.2.文件的查找 3.路径 3.1挂载 3.2如何理解挂载 1.创…

【QT学习】8.qt事件处理机制,事件过滤器,自定义事件

1.qt事件处理机制 事件处理&#xff1a; 当用户移动鼠标的时候 &#xff0c;创建一个 鼠标移动事件对象 然后把这个对象放到 事件队列里面去&#xff0c;事件管理器 从队列中 取出事件&#xff0c;然后 调用其对应的事件处理函数。 多态机制&#xff1a; &#x…

2023年图灵奖颁发给艾维·维格森(Avi Wigderson),浅谈其计算复杂性理论方面做出的重要贡献

Avi Wigderson是一位以色列计算机科学家&#xff0c;他在计算复杂性理论方面做出了重要的贡献&#xff0c;并对现代计算产生了深远的影响。 Wigderson的主要贡献之一是在证明计算复杂性理论中的基本问题的困难性方面。他证明了许多经典问题的困难性&#xff0c;如图论中的图同构…

Day08React——第八天

useEffect 概念&#xff1a;useEffect 是一个 React Hook 函数&#xff0c;用于在React组件中创建不是由事件引起而是由渲染本身引起的操作&#xff0c;比如发送AJAx请求&#xff0c;更改daom等等 需求&#xff1a;在组件渲染完毕后&#xff0c;立刻从服务器获取频道列表数据…

每天五分钟机器学习:神经网络模型参数的选择

本文重点 在深度学习和人工智能的浪潮中,神经网络作为其中的核心力量,发挥着举足轻重的作用。然而,神经网络的性能并非一蹴而就,而是需要经过精心的参数选择和调优。 神经网络由大量的神经元组成,每个神经元之间通过权重进行连接。这些权重,以及神经元的偏置、激活函数…

Adobe Acrobat PDF 2024

Adobe Acrobat PDF 2024正式发布&#xff01;支持Windows和macOS系统&#xff0c;新界面做了轻微调整。 下载地址 Windows客户端&#xff1a;https://www.123pan.com/s/f43eVv-GKZKd.html macOS客户端&#xff1a;https://www.123pan.com/s/f43eVv-PKZKd.html

idea在controller或者service使用ctrl+alt+b进入方法后,如何返回到 进入前的那一层

idea在controller或者service使用ctrlaltb进入方法后&#xff0c;如何返回到进入方法的最外层 解决方案使用 ctrlalt ← /→← /→ 键盘上的左右键盘

数据结构练习-算法与时间复杂度

----------------------------------------------------------------------------------------------------------------------------- 1. 设n是描述问题规模的非负整数&#xff0c;下列程序段的时间复杂度是( )。 x0;while(n>(x1)*(x1)xx1; A.O(logn) B.O(n^(1/2)) C.O(n)…

【周总结】总结下这周的工作、(hashmap)知识巩固等

总结 这周开发任务已经全部结束&#xff0c;主要是在修改一些 jira 问题 需要反思的是&#xff0c;中间改造接口时&#xff0c;数据库表需要新增一个字段&#xff0c;这个 sql 脚本忘记加到 basetable.sql 脚本里面了&#xff0c;这样如果是新建的项目&#xff0c;创建的时候不…

百万级别mysql性能耗时自测

注&#xff1a;实际情况会因建表语句和服务器的配置造成偏差 测试环境 &#xff1a;8核CPU 16G运行内存 建表语句&#xff1a; CREATE TABLE user (id bigint(11) NOT NULL AUTO_INCREMENT,username varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,birthday varchar(255)…

AppWizard的软件开发GUI的使用记录

前言 这个软件是针对于EmWin6.0以上的这个软件在emWin的基础上又封装了一层,也只提供的API函数.基于消息事件为核心&#xff08;个人理解&#xff09;一些组件的之间的交互可以通过软件界面进行配置,比较方便本次是基于模拟器进行测试记录,观察api 按键和文本之间的关联 通过…

软考141-上午题-【软件工程】-杂题+小结

一、杂题 真题1&#xff1a; 真题2&#xff1a; 真题3&#xff1a; 真题4&#xff1a; 真题5&#xff1a; 真题6&#xff1a; 真题7&#xff1a; 真题8&#xff1a; 真题9&#xff1a; 真题10&#xff1a; 真题11&#xff1a; 真题12&#xff1a; 真题13&#xff1a; 真题14&a…

深入剖析Spring框架:循环依赖的解决机制

你好&#xff0c;我是柳岸花开。 什么是循环依赖&#xff1f; 很简单&#xff0c;就是A对象依赖了B对象&#xff0c;B对象依赖了A对象。 在Spring中&#xff0c;一个对象并不是简单new出来了&#xff0c;而是会经过一系列的Bean的生命周期&#xff0c;就是因为Bean的生命周期所…

05集合-CollectionListSet

Collection体系的特点、使用场景总结 如果希望元素可以重复&#xff0c;又有索引&#xff0c;索引查询要快? 用ArrayList集合, 基于数组的。(用的最多) 如果希望元素可以重复&#xff0c;又有索引&#xff0c;增删首尾操作快? 用LinkedList集合, 基于链表的。 如果希望增…

亚马逊测评自养号策略:手机与PC结合的重要性

亚马逊测评的核心关键技术在于精心培养买家账号&#xff0c;之所以称之为核心关键&#xff0c;原因在于测评下单的首要条件是拥有一个活跃的买家账号。买家账号并非一次性使用&#xff0c;因此&#xff0c;养号过程显得至关重要。然而&#xff0c;在养号的过程中&#xff0c;很…

Python基础03-深入探索Python字典操作

在Python中&#xff0c;字典是一种非常强大和灵活的数据结构&#xff0c;可以存储键值对&#xff0c;并提供了许多方法来操作这些键值对。本文将深入探讨Python字典的各种操作&#xff0c;包括如何创建、修改、合并和查找字典中的元素。 1. 创建字典 要创建一个字典&#xff…

【数字电路与系统】【北京航空航天大学】实验:时序逻辑设计——三色灯开关(三)、功能仿真测试

本次实验&#xff08;一&#xff09;见博客&#xff1a;【数字电路与系统】【北京航空航天大学】实验&#xff1a;时序逻辑设计——三色灯开关&#xff08;一&#xff09;、实验指导书 本次实验&#xff08;二&#xff09;见博客&#xff1a;【数字电路与系统】【北京航空航天…

【gdb调试】在ubuntu环境使用gdb调试一棵四层二叉树的数据结构详解

目录 &#x1f31e;1. 整体思路 &#x1f31e;2. 准备内容 &#x1f33c;2.1 配置.c文件 &#x1f33c;2.2 准备测试程序 &#x1f33c;2.3 GDB调试基础 &#x1f31e;3. GDB调试四层二叉树 &#x1f33c;3.1 测试程序分析 &#x1f33c;3.2 gdb分析 &#x1f33b;1. …

到2031年,5G服务市场预计将超过9194亿美元

根据 Transparency Market Research 最近的一份报告&#xff0c;到 2031 年&#xff0c;全球 5G 服务市场预计将超过 9194 亿美元。 这相当于 30.8% 的复合年增长率 (CAGR)&#xff0c;预计 2022 年市场价值将达到 827 亿美元。 随着 5G 技术的吸引力日益增强&#xff0c;它正在…