Flutter - 底部多选弹框组件

demo 地址: https://github.com/iotjin/jh_flutter_demo
代码不定时更新,请前往github查看最新代码

有时需要弹框选择多个数据,因此写了个底部多选弹框组件
支持搜索,设置默认选中数据,暗黑模式适配

效果图

在这里插入图片描述

使用方法


final multiDictArr = [{'label': '类型一', 'value': '1'},{'label': '类型二', 'value': '2'},{'label': '类型三', 'value': '3'},{'label': '类型四', 'value': '4'},{'label': '类型五', 'value': '5'},{'label': '类型六', 'value': '6'},{'label': '类型七类型七类型七类型七', 'value': '7'},{'label': '类型八类型八类型八类型八类型八类型八类型八类型八类型八类型八', 'value': '8'},{'label': '类型九', 'value': '9'},
];JhMultiPicker.show(context, data: multiDictArr, values: ['3', '5'], title: '选择类型',clickCallBack: (selectValues, selectItemArr) {print('selectValues==  $selectValues');print('selectItemArr==  $selectItemArr');showText(selectValues);});

jh_multi_picker代码

///  jh_multi_picker.dart
///
///  Created by iotjin on 2023/08/28.
///  description: 底部多选弹框// ignore_for_file: library_private_types_in_public_apiimport 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '/jh_common/jh_form/jh_searchbar.dart';
import '/jh_common/utils/jh_common_utils.dart';
import '/project/configs/colors.dart';
import '/project/provider/theme_provider.dart';
import '/project/routes/jh_nav_utils.dart';const String _labelKey = 'label';
const String _valueKey = 'value';
const String _titleText = '请选择';
const String _cancelText = '取消';
const String _confirmText = '确定';
const String _searchHintText = '搜索';const double _headerHeight = 50.0;
const double _headerRadius = 10.0;
const double _headerLineHeight = 0.5;
const double _titleFontSize = 18.0;
const double _btnFontSize = 17.0;
const double _textFontSize = 16.0;/// 选择回调,返回所有选中的values数组和所有item数组
typedef _ClickCallBack = void Function(dynamic selectValues, dynamic selectItemArr);class JhMultiPicker {static bool _isShowPicker = false;static void show(BuildContext context, {required List data, // 数据源数组String labelKey = _labelKey, // 数据源数组的文字字段String valueKey = _valueKey, // 数据源数组的数值字段String title = _titleText,List values = const [], // 默认选中的数组(一维数组),通过valuesKey确定是根据value还是label进行比较,最好使用唯一值作为元素String valuesKey = _valueKey, // 选中数组内元素使用的字段,对应valueKey或者labelKeybool isShowSearch = true,String searchHintText = _searchHintText,bool isShowRadius = true,_ClickCallBack? clickCallBack,}) {if (_isShowPicker || data.isEmpty) {return;}var radius = isShowRadius ? _headerRadius : 0.0;showModalBottomSheet<void>(context: context,// 使用true则高度不受16分之9的最高限制isScrollControlled: false,// 设置圆角shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(radius),topRight: Radius.circular(radius),),),// 抗锯齿clipBehavior: Clip.antiAlias,builder: (BuildContext context) {return SafeArea(child: JhMultiPickerView(data: data,labelKey: labelKey,valueKey: valueKey,title: title,values: values,valuesKey: valuesKey,isShowSearch: isShowSearch,searchHintText: searchHintText,clickCallBack: clickCallBack,),);},).then((value) => _isShowPicker = false);}
}class JhMultiPickerView extends StatefulWidget {const JhMultiPickerView({Key? key,required this.data,this.labelKey = _labelKey,this.valueKey = _valueKey,this.title = _titleText,this.values = const [],this.valuesKey = _valueKey,this.isShowSearch = true,this.searchHintText = _searchHintText,this.clickCallBack,}) : super(key: key);final List? data; // 数据源数组final String labelKey; // 数据源数组的文字字段final String valueKey; // 数据源数组的数值字段final String title;final List values; // 默认选中的数组(一维数组),通过valuesKey确定是根据value还是label进行比较,最好使用唯一值作为元素final String valuesKey; // 选中数组内元素使用的字段,对应valueKey或者labelKeyfinal bool isShowSearch;final String searchHintText;final _ClickCallBack? clickCallBack;State<JhMultiPickerView> createState() => _JhMultiPickerViewState();
}class _JhMultiPickerViewState extends State<JhMultiPickerView> {late List<dynamic> _selectedValues = [];// 搜索数据List _searchData = [];bool _isShowSearchResult = false;String _searchKeyword = '';void initState() {super.initState();_selectedValues = List.from(widget.values);}Widget build(BuildContext context) {return _body();}_body() {// 默认颜色var bgColor = KColors.dynamicColor(context, KColors.kPickerBgColor, KColors.kPickerBgDarkColor);var lineColor = KColors.dynamicColor(context, KColors.kLineColor, KColors.kLineDarkColor);return Container(color: bgColor,child: Column(children: <Widget>[_header(),SizedBox(height: _headerLineHeight, child: Container(color: lineColor)),_searchBar(),_mainWidget(),],),);}_header() {// 默认颜色var headerColor = KColors.dynamicColor(context, KColors.kPickerHeaderColor, KColors.kPickerHeaderDarkColor);var titleColor = KColors.dynamicColor(context, KColors.kPickerTitleColor, KColors.kPickerTitleDarkColor);var btnColor = KColors.dynamicColor(context, KColors.kPickerBtnColor, KColors.kPickerBtnDarkColor);return Container(height: _headerHeight,color: headerColor,child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [GestureDetector(child: Container(padding: const EdgeInsets.only(left: 15),child: Text(_cancelText, style: TextStyle(fontSize: _btnFontSize, color: btnColor)),),onTap: () {widget.clickCallBack?.call([], []);JhNavUtils.goBack(context);},),Text(widget.title, style: TextStyle(fontSize: _titleFontSize, color: titleColor)),GestureDetector(child: Container(padding: const EdgeInsets.only(right: 15),child: Text(_confirmText, style: TextStyle(fontSize: _btnFontSize, color: btnColor)),),onTap: () {widget.clickCallBack?.call(_selectedValues, _getSelectItemList());JhNavUtils.goBack(context);}),],),);}Widget _mainWidget() {List dataArr = _isShowSearchResult ? _searchData : (widget.data ?? []);return Expanded(child: ListView.builder(shrinkWrap: true,itemCount: dataArr.length,itemBuilder: (BuildContext context, int index) {return _buildItem(dataArr[index], index);},),);}_buildItem(item, index) {// TODO: 通过ThemeProvider进行主题管理final provider = Provider.of<ThemeProvider>(context);var themeColor = KColors.dynamicColor(context, provider.getThemeColor(), KColors.kThemeColor);var selectValue = widget.valuesKey == widget.valueKey ? item[widget.valueKey] : item[widget.labelKey];return CheckboxListTile(title: Text(item[widget.labelKey].toString(), style: const TextStyle(fontSize: _textFontSize)),value: _selectedValues.contains(selectValue),activeColor: themeColor,onChanged: (bool? checked) {setState(() {if (checked ?? false) {_selectedValues.add(selectValue);} else {_selectedValues.remove(selectValue);}// widget.clickCallBack?.call(_selectedValues, _getSelectItemList());});},);}_getSelectItemList() {var newList = (widget.data ?? []).where((item) => _selectedValues.contains(item[widget.valueKey])).toList();return newList;}Widget _searchBar() {Widget searchbar = JhSearchBar(hintText: widget.searchHintText,text: _searchKeyword,inputCallBack: (value) {JhCommonUtils.debounce(() {setState(() {_searchKeyword = value;if (value.isNotEmpty) {_searchData = _getSearchData(value);_isShowSearchResult = _searchData.isNotEmpty;} else {_isShowSearchResult = false;}});}, 500);},);return !widget.isShowSearch ? Container() : searchbar;}/// 根据搜索文字过滤数据_getSearchData(keyword) {var newList = (widget.data ?? []).where((item) => item[widget.labelKey].toLowerCase().contains(keyword.toLowerCase())).toList();return newList;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python+”高光谱遥感数据处理与机器学习深度应用丨高光谱数据预处理-机器学习-深度学习-图像分类-参数回归

涵盖高光谱遥感数据处理的基础、python开发基础、机器学习和应用实践。重点解释高光谱数据处理所涉及的基本概念和理论&#xff0c;旨在帮助学员深入理解科学原理。结合Python编程工具&#xff0c;专注于解决高光谱数据读取、数据预处理、高光谱数据机器学习等技术难题&#xf…

DOCKER本地仓库

概述 随着docker的应用越来越多&#xff0c;安装部署越来越方便&#xff0c;批量自动化的镜像生成和发布都需要docker仓库的本地化应用。 试用了docker的本地仓库功能&#xff0c;简单易上手&#xff0c;记录下来以备后用。 环境 centos&#xff1a;CentOS release 7.0 (F…

2015架构真题(五十)

供应链中信息流覆盖了供应商、制造商和分销商&#xff0c;信息流分为需求信息流和供应信息流&#xff0c;&#xff08;&#xff09;属于需求信息流&#xff0c;&#xff08;&#xff09;属于供应信息流。 库存记录生产计划商品入库单提货发运单 客户订单采购合同完工报告单销售…

伦敦金的交易时间究竟多长?

接触过伦敦金交易的投资者&#xff0c;应该都知道自己根本不用担心市场上没有交易的机会&#xff0c;因为它全天的交易时间长达20多个小时&#xff0c;也就是在每一个正常的交易日&#xff0c;除去交易平台中途短暂的系统维护时间&#xff0c;投资者几乎全天都可以做盘。 伦敦金…

自动驾驶学习笔记(三)——场景设计

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 场景设计平台 场景地图 场景基本…

【学习笔记】数据一致性分发

为什么要数据分发 微服务中&#xff0c;每个服务都有独立的数据源&#xff0c;这使得数据同步成为难题。 拉模式or推模式&#xff1f; 拉模式存在的问题 由于网络延迟&#xff0c;拉取的数据不一定是最新的 如果频繁向另一服务拉取数据&#xff0c;会给服务造成压力&#xf…

MVVM 与 MVC区别和应用场景?

MVVM 和 MVC 1. MVC2. MVVM 1. MVC MVC 是 Model View Controller 的缩写 Model&#xff1a;模型层&#xff0c;是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。View&#xff1a;视图层&#xff0c;用户界面渲染逻辑&#xff0c;通常视图…

Redis实战:Redis在Java中的基本使用

本片将介绍 Redis 在 Java 中的基本使用 文章目录 1、使用jedis操作redis1.1、Jedis简介1.2、引入jedis的Maven依赖1.2、获取连接1.3、使用实例 2、对于JedisPooled的使用2.1、使用JedisPooled2.2、关于连接池 3、SpringBoot下使用Redis3.1、引入Maven依赖3.2、配置Redis连接3.…

MDK自动生成带校验带SVN版本号的升级文件

MDK自动生成带校验带SVN版本号的升级文件 获取SVN版本信息 确保SVN安装了命令行工具&#xff0c;默认安装时不会安装命令行工具 编写一个模板头文件 svn_version.temp.h, 版本号格式为 1_0_0_SVN版本号 #ifndef __SVN_VERSION_H #define __SVN_VERSION_H#define SVN_REVISIO…

微信小程序服务通知(订阅消息)定时推送消息功能

首先先说项目需求&#xff1a;向预约参观的用户提前一天晚上8点推送消息。小程序端主要用到的API是我是小程序用到的API。以及服务端用到的API&#xff1a;我是服务端用到的API。 1. 开通订阅消息功能 (1)、 首先需要在小程序管理后台开通订阅消息功能。没开通前如下图所示: …

《机器学习》第5章 神经网络

文章目录 5.1 神经元模型5.2 感知机与多层网络5.3 误差逆传播算法5.4 全局最小与局部最小5.5 其他常见神经网络RBF网络ART网络SOM网络级联相关网络Elman网络Boltzmann机 5.6 深度学习 5.1 神经元模型 神经网络是由具有适应性的简单单元组成的广泛并行互连的网络&#xff0c;它…

网络安全概述——常见网络攻击与网络病毒、密码体制、安全协议等

目录 1、信息安全五大要素 2、常见的网络攻击类型 2-1&#xff09;网络攻击的分类&#xff1a; 2-2&#xff09;常见网络攻击&#xff1a; DOS 攻击的分类&#xff1a; 2-3&#xff09;常见网络攻击的防范措施 3、计算机病毒 3-1&#xff09;常见病毒的前缀及其简要描述…