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

news2024/11/14 14:00:43

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

在这里插入图片描述

//表单组件
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']),
    ];

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【BUG】Hexo|GET _MG_0001.JPG 404 (Not Found),hexo博客搭建过程图片路径正确却找不到图片

我的问题 我查了好多资料&#xff0c;结果原因是图片名称开头是_则该文件会被忽略。。。我注意到网上并没有提到这个问题&#xff0c;遂补了一下这篇博客并且汇总了我找到的所有解决办法。 具体检查方式&#xff1a; hexo生成一下静态资源&#xff1a; hexo g会发现这张图片…

配置静态路由实现全网互通

1、实验环境 如图下所示&#xff0c;三台路由器R1&#xff0e;R2&#xff0c;R3两两互连&#xff0c;每台路由器上都配置了Loopback地址模拟网络环境。 2、需求描述 需要在三台路由器上配置静态路由&#xff0c;以实现各网段之间的互通。 若要实现全网互通,必须明确如下两个问…

【GlobalMapper精品教程】075:将影像的颜色赋予点云实现点云真彩色

文章目录 一、加载点云与影像数据二、将影像色彩赋予点云三、保存色彩点云四、注意事项一、加载点云与影像数据 加载本实验数据(data075.rar)中的影像、点云数据,并用Globalmapper提供的卷帘工具(快速浏览图像)查看: 启动卷帘工具,左右拖动实现卷帘效果: 影像VS点云:…

【硬十宝典】——1.4【基础知识】电源完整性——理解与设计

定义&#xff1a; 电源完整性&#xff08;Power integrity&#xff09;简称PI&#xff0c;是确认电源来源及目的端的电压及电流是否符合需求。 电源完整性在现今的电子产品中相当重要。有几个有关电源完整性的层面&#xff1a;芯片层面、芯片封装层面、电路板层面及系统层面。…

EelasticSearch使用

1. Easy-ES介绍 Easy-Es 2. 导入依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions>//排除框架中原有的依赖包<exclusion><groupId>org.elast…

Elasticsearch:(二)2.安装kibana

1.环境安装介绍: 安装java环境安装Elasticsearch安装kibana安装Elasticsearch-head插件 本节文章主要讲解kibana的安装。 2.下载 下载Elasticsearch对应的版本,参考官方自身产品兼容版本:支持一览表 | Elastic 下载地址:Kibana 7.17.20 | Elastic Kibana 7.17.20 | Ela…

机器学习与深度学习 --李宏毅(笔记与个人理解)Day 20

Day 20 RNN 2 实际使用和其他应用 在实际的学习&#xff08;training&#xff09;过程中是如何工作的&#xff1f; step 1 Loss step 2 training Graindent Descent 反向传播的进阶版 – BPTT CLIpping 设置阈值~ 笑死昨天刚看完关伟说的有这玩意的就不是好东西 Why&#xff1…

FastChat启动与部署通义千问大模型

FastChat简介 FastChat is an open platform for training, serving, and evaluating large language model based chatbots. FastChat powers Chatbot Arena, serving over 10 million chat requests for 70 LLMs.Chatbot Arena has collected over 500K human votes from sid…

详细剖析多线程4----锁策略(八股文/面试常考)

文章目录 前言一、常见锁策略(八股文)1.1乐观锁和悲观锁1.2轻量级锁和重量级锁1.3自旋锁和挂起等待锁1.4普通互斥锁和读写锁1.5公平锁和非公平锁1.6可重入锁和不可重入锁1.7总结 二、synchronized内部原理三、CAS四、JUC(java.util.concurrent) 的常见类4.1Callable 接⼝4.2Ree…

基于SpringBoot+Vue七匹狼商城系统的设计与实现

系统介绍 近年来随着社会科技的不断发展&#xff0c;人们的生活方方面面进入了信息化时代。计算机的普及&#xff0c;使得我们的生活更加丰富多彩&#xff0c;越来越多的人使用通过网络来购买各类的商品。早期商品的销售和购买都是通过实体店&#xff0c;这种购买方式需要耗费…

openGauss学习笔记-267 openGauss性能调优-TPCC性能调优测试指导-网络配置-网卡多中断队列设置

文章目录 openGauss学习笔记-267 openGauss性能调优-TPCC性能调优测试指导-网络配置-网卡多中断队列设置267.1 操作步骤 openGauss学习笔记-267 openGauss性能调优-TPCC性能调优测试指导-网络配置-网卡多中断队列设置 本章节主要介绍openGauss数据库内核基于鲲鹏服务器和openE…

[jinja2]模板访问对象属性

甚至可以用. 访问字典 .访问一般用得是最多的

R绘图--峰峦图/山脊图/ggridges包

山脊图是部分重叠的线图&#xff0c;可产生山脉的印象。它们对于可视化分布随时间或空间的变化非常有用。 绘图 加载包和数据 # install.packages("ggridges") # 加载包 library(ggplot2) library(ggridges) library(viridis) library(tidyverse)# 准备输入数据 d…

Java发送邮件 启用SSL

使用的maven依赖: <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.4.7</version> </dependency> 配置文件mail.properties如下: # 邮箱配置 email.username=your-email@exa…

const成员函数 以及 取地址及const取地址操作符重载

目录 const成员函数 结论&#xff1a; 取地址及const取地址操作符重载 const成员函数 将const 修饰的 “ 成员函数 ” 称之为 const成员函数 &#xff0c; const 修饰类成员函数&#xff0c;实际修饰该成员函数的&#xff08;*this&#xff09; &#xff0c;表明在该成员函数…

嵌入式Linux开发实操(十七):Linux Media Infrastructure userspace API

视频和无线电流媒体设备使用的Linux内核到用户空间API,包括摄像机、模拟和数字电视接收卡、AM/FM接收卡、软件定义无线电(SDR)、流捕获和输出设备、编解码器设备和遥控器。典型的媒体设备硬件如下: 媒体基础设施API就是用于控制此类设备的,分五个部分。 第一部分V4L2 API…

【Interconnection Networks 互连网络】Dragonfly Topology 蜻蜓网络拓扑

蜻蜓拓扑 Dragonfly Topology 1. 拓扑参数2. Topology Description 拓扑描述3. Topology Variations 拓扑变体 蜻蜓拓扑 Dragonfly Topology 1. 拓扑参数 Dragonfly拓扑参数&#xff1a; N N N: 网络中终端(terminal)的总数量 p p p: 连接到每个路由器的终端数量 a a a: 每…

【网站项目】“最多跑一次”小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

微调Llama3实践并基于Llama3构建心理咨询EmoLLM

Llama3 Xtuner微调Llama3 EmoLLM 心理咨询师