Flutter 底部弹窗如何实现多项选择

作者:岛上码农 时间:2023-06-24 17:08:17 

Flutter 底部弹窗如何实现多项选择

多选和单选的不同之处

单选的时候,选中一个就可以直接把结果返回,因此本身底部弹窗无需状态管理。但到多选的时候,需要知道当前选中的选项,有选项被点击的时候需要存储下来,当再次被点击的时候要清空这个选项,同时界面还需要同步更新,因此就涉及到状态管理了。

实现方式

在Flutter 中提供了一个 StatefulBuilder 的类,提供了一个 builder方法构建有状态组件,并且提供了状态更新方法,因此在里面完成状态管理。


StatefulBuilder(builder: (context1, setState) {
 return Widget;
}
)

在这个 builder 方法中,setState 其实就是对应状态组件的setState 对应的方法,这个 state 就是用于控制 StatefulBuilder 生成的组件的状态的。这种方式有点类似于 React 的 useState 的钩子函数用法。

界面变更

首先底部弹窗的头部组件要更换,需要增加确认按钮,将构建该组件的方法抽离出来如下所示:


Widget _getModalSheetHeaderWithConfirm(String title,
     {Function onCancel, Function onConfirm}) {
 return SizedBox(
   height: 50,
   child: Row(
     children: [
       IconButton(
         icon: Icon(Icons.close),
         onPressed: () {
           onCancel();
         },
       ),
       Expanded(
         child: Center(
           child: Text(
             title,
             style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
           ),
         ),
       ),
       IconButton(
           icon: Icon(
             Icons.check,
             color: Colors.blue,
           ),
           onPressed: () {
             onConfirm();
           }),
     ],
   ),
 );
}

通过这个方法可以通过外部参数传入标题,取消响应事件回调和确认事件回调,通用性更强。

其次是选项需要有图标标记,选中时显示为勾选框,未选中时是空白框,这需要通过状态数据来控制。这里我们使用了 Set 类型,保证选中的数据集是不重复的。在点击选项时,如果选项对应数组的下标在 Set 内,则从中移出,表示取消选择;如果不在 Set内,则加入其中,表示选中。这个过程需要包在 state 里,以更新界面。通过列表元素当前的下标是否在 Set 内,如果在则显示为选中,不在则显示未选中。

最后是确认事件的回调,确认后将 Set 的元素转换为数组返回,然后供上级业务使用选中的下标数组判断选择了那些数据。

代码实现

关键代码实现如下,重点关注一下StatefulBuilder的使用和利用 Set 这一数据类型对应的选择和取消选择的操作业务逻辑。


Future<List<int>> _showMultiChoiceModalBottomSheet(
     BuildContext context, List<String> options) async {
 Set<int> selected = Set<int>();
 return showModalBottomSheet<List<int>>(
   backgroundColor: Colors.transparent,
   isScrollControlled: true,
   context: context,
   builder: (BuildContext context) {
     return StatefulBuilder(builder: (context1, setState) {
       return Container(
         clipBehavior: Clip.antiAlias,
         decoration: BoxDecoration(
           color: Colors.white,
           borderRadius: BorderRadius.only(
             topLeft: const Radius.circular(20.0),
             topRight: const Radius.circular(20.0),
           ),
         ),
         height: MediaQuery.of(context).size.height / 2.0,
         child: Column(children: [
           _getModalSheetHeaderWithConfirm('多选底部弹窗',
               onCancel: () {
                 Navigator.of(context).pop();
               },
               onConfirm: () {
                 Navigator.of(context).pop(selected.toList());
               },
           ),
           Divider(height: 1.0),
           Expanded(
             child: ListView.builder(
               itemBuilder: (BuildContext context, int index) {
                 return ListTile(
                   trailing: Icon(
                       selected.contains(index)
                           ? Icons.check_box
                           : Icons.check_box_outline_blank,
                       color: Theme.of(context).primaryColor),
                   title: Text(options[index]),
                   onTap: () {
                     setState(() {
                       if (selected.contains(index)) {
                         selected.remove(index);
                       } else {
                         selected.add(index);
                       }
                     });
                   },
                 );
               },
               itemCount: options.length,
             ),
           ),
         ]),
       );
     });
   },
 );
}

总结

本篇介绍了底部弹窗实现多选的方式,其中实现的方式还可以有很多种,例如直接在自定义组件中使用有状态组件。这里介绍的方法可以作为一个参考,通过动态构建有状态组件能够简单快速地实现底部弹窗的多选功能。

来源:https://juejin.cn/post/6972106616925585444

标签:Flutter,底部弹窗,多项选择
0
投稿

猜你喜欢

  • linux下C语言中的mkdir函数与rmdir函数

    2023-07-07 14:16:16
  • Flutter Widgets粘合剂CustomScrollView NestedScrollView滚动控件

    2023-07-06 01:24:29
  • IOS 实现摇一摇的操作

    2023-07-02 13:46:53
  • android TextView中识别多个url并分别点击跳转方法详解

    2023-06-21 04:42:32
  • springboot大文件上传、分片上传、断点续传、秒传的实现

    2023-06-16 02:18:30
  • C++ lambda函数详解

    2023-06-20 07:49:43
  • Android Studio kotlin生成编辑类注释代码

    2023-06-16 12:03:20
  • Json操作库DynamicJson使用指南

    2023-06-17 10:17:35
  • C++右值引用与move和forward函数的使用详解

    2023-07-05 19:27:33
  • C#创建临时文件的方法

    2023-06-16 14:32:36
  • Android kotlin使用注解实现防按钮连点功能的示例

    2023-07-02 11:58:06
  • c# Selenium爬取数据时防止webdriver封爬虫的方法

    2023-06-24 07:50:51
  • android自定义环形对比图效果

    2023-06-15 19:49:19
  • Java抢红包的红包生成算法

    2023-06-23 20:52:04
  • Android 动画之TranslateAnimation应用详解

    2023-06-27 06:17:59
  • Flutter 使用fluro的转场动画进行页面切换

    2023-06-17 11:49:26
  • flutter ExpansionTile 层级菜单的实现

    2023-06-15 16:04:01
  • C语言头文件<string.h>函数详解

    2023-07-01 18:59:34
  • C# BitArray(点矩阵)转换成int和string的方法实现

    2023-06-18 07:33:44
  • android studio2.3如何编译动态库的过程详解

    2023-07-11 03:47:48
  • asp之家 软件编程 m.aspxhome.com