分享一个实现侧滑菜单的Flutter页面所遇到的问题与解决思路

最近做了一个需要实现侧滑菜单相关的Flutter新页面,页面布局结构稍微比较复杂。因此,做完之后就对研发的过程做出一些整理。
以下主要整理跟侧滑菜单相关的内容。直奔主题,首先,要实现侧滑菜单,有以下几个方案。而本次选取的方案,是使用Scaffold 的 endDrawer的方式。在使用这个方案的同时,也是遇到了一些问题……

方案一:使用 Scaffold 的 endDrawer 属性

简单例子:

当需要在Scaffold中使用endDrawer时,可以按照以下简单例子进行操作:

class TestPage extends StatelessWidget {final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();Widget build(BuildContext context) {return Scaffold(key: _scaffoldKey,appBar: AppBar(title: Text('Scaffold with endDrawer'),),body: Center(child: Text('Hello, World!'),),endDrawer: Drawer(child: ListView(children: [ListTile(leading: Icon(Icons.settings),title: Text('Settings'),),ListTile(leading: Icon(Icons.help),title: Text('Help'),),],),),floatingActionButton: FloatingActionButton(onPressed: () {_scaffoldKey.currentState!.openEndDrawer();},child: Icon(Icons.menu),),);}
}

在这个例子中,我们创建了一个简单的Scaffold,其中包含一个AppBar、一个中心对齐的文本和一个FloatingActionButton。
通过设置endDrawer属性,我们在Scaffold的右侧添加了一个抽屉式的侧边栏。当用户点击FloatingActionButton时,通过_scaffoldKey.currentState!.openEndDrawer()方法打开endDrawer。

项目实现卡点与解决方案

事实证明,需求永远没有那么简单实现,比如,现在需要实现的是:类似Android中,viewpager的方式。这可以这么实现:page中套着一层ExtendedNestedScrollView,存在着多个TabBarView。
而卡点就在于,弹出侧滑菜单的点击事件是在TabBarView中。因此,如果直接在TabBarView中通过Scaffold 的 endDrawer 实现抽屉效果。则会发现,抽屉的大小只有TabBarView那么大,无法铺满屏幕。
因此,解决方案是:
将抽屉布局移到最外层的Scaffold 去实现。然后,内部TabBarView布局里的widget点击事件去调用这个打开这个弹窗。这个方案是可行的,但是麻烦的是内外层之间的数据交互,但是也有两个方案去实现:

  1. 通过回调的方式实现。但是,实践之后,会发现,回调存在一个问题。就是抽屉布局里的操作,需要更新到最外层page的UI效果和数据,同时也需要更新到内部TabBarView布局里的数据进行刷新相关处理。而TabBarView内的数据,产品又要求需要根据抽屉布局内部的筛选数据,及时更新,加上TabBarView有很多tab,因此,这块从性能上考虑,是必须做懒加载处理的。而Flutter其实已经默认实现了,这是一个点。
    因此,回调的方式,一来,我需要在外部去持有这个内部page,二来,需要在page内部处理回调更新相关操作。而一个比较复杂的场景是:首次进入页面,TabBarView内部的数据是懒加载,此时是没有更新数据,也没有执行相关操作。因此,如果使用回调的方式,会导致非当前页面的tab数据出现错乱(没有使用筛选条件请求接口)。而如果每个页面都加载过了之后,后续又难以响应筛选条件的变化。因此,这个方案不适用当前业务场景。

  2. 通过状态管理的方式实现。通过外部去持有内部的ViewModel,当数据筛选的时候,再去调用内部的ViewMode的对应方法。并在这个过程中去处理上面所说的两个问题。通过标志进行判断是否初次加载,通过筛选项变化监听去判断是否需要重新加载数据。但是,这里有一个需要值得注意的地方。因为在使用Scaffold中使用endDrawer时,页面会重新加载:

  • 当我们在Scaffold中设置了endDrawer属性时,endDrawer实际上是作为Scaffold的子Widget存在的。
  • 当我们打开或关闭endDrawer时,Scaffold的状态会发生变化,因为endDrawer的显示状态是Scaffold的一部分。
  • 当Scaffold的状态发生变化时,Flutter框架会调用build方法来重新构建Scaffold及其子树。
  • 在重新构建过程中,Flutter会重新创建endDrawer及其子树,以确保它们与新的状态匹配。

因此,当我们打开或关闭endDrawer时,Scaffold会重新加载页面,因为endDrawer是Scaffold的一部分,而Scaffold的状态发生了变化。而又因为这个需求业务的需要,页面是需要请求接口,才能确定tab数据,然后再进行创建ExtendedNestedScrollView、TabBarView等系列Widget的。因此,这里的创建内部Page,需要唯一性,不能在builder属性中进行创建,否则这会导致重复创建,进而显示异常问题。需要把这段创建的代码抽出来,并只在接口请求结束后执行一次。

方案二:使用 showModalBottomSheet。

Flutter的showModalBottomSheet函数是一个非常有用的方法,它可以在屏幕底部显示一个模态底部表单或菜单。它通常用于显示与当前页面相关的附加信息或操作。

showModalBottomSheet函数有几个参数,下面是它们的详细说明:

  1. context:BuildContext对象,用于获取当前页面的上下文。
  2. builder:WidgetBuilder函数,用于构建底部表单或菜单的内容。它接收一个BuildContext参数,并返回一个Widget。
  3. isScrollControlled:一个可选的布尔值,用于指定是否将底部表单或菜单的高度限制为屏幕高度的一部分。默认情况下,它为false,即底部表单或菜单的高度将适应内容的高度。
  4. backgroundColor:一个可选的颜色值,用于设置底部表单或菜单的背景颜色。
  5. shape:一个可选的ShapeBorder对象,用于设置底部表单或菜单的形状。
  6. elevation:一个可选的double值,用于设置底部表单或菜单的阴影高度。

下面是一个使用showModalBottomSheet函数的例子:

void _showBottomSheet(BuildContext context) {showModalBottomSheet(context: context,isScrollControlled: true,backgroundColor: Colors.transparent,builder: (BuildContext context) {return Test(isFree: isFree,goodsLiningModel: data,fabricContent: fabricContent);});
}

缺点:少了侧滑效果,另外状态栏的处理相比Scaffold 的 endDrawer,处理起来笔记麻烦点。更适合于从底部弹起。可以作为备选方案。

方案三:通过Stack的方式

将主布局和抽屉布局包裹起来。根据操作来判断抽屉布局的显示还是隐藏。
这个就不细说了。主要就是通过Visibility来进行控制。

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

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

相关文章

类型特质和静态断言

static_assert( constant-expression, string-literal );static_assert( constant-expression ); // C17 (Visual Studio 2017 and later) constant-expression 可以转换为布尔值的整型常量表达式。 如果计算出的表达式为零 (false)&#xff0c;则显示 string-literal 参数&…

PyTorch|view(),改变张量维度

在构建自己的网络时&#xff0c;了解数据经过每个层后的形状变化是必须的&#xff0c;否则&#xff0c;网络大概率会出现问题。PyToch张量有一个方法&#xff0c;叫做view(),使用这个方法&#xff0c;我们可以很容易的对张量的形状进行改变&#xff0c;从而符合网络的输入要求。…

React 18中新钩子 useDeferredValue 使用

React是一个流行的用于构建用户界面的JavaScript库,它不断发展以为开发人员提供优化性能的工具。 React 18中引入的此类工具之一是useDeferredValue钩子,它旨在通过优先渲染更新来提高应用程序的性能。 useDeferredValue钩子是什么? useDeferredValue钩子是React性能优化工…

SAP PP配置学习(五)

查找 四、 其它 设置 MM 过帐号码范围 定义凭证号码范围 OB52 打开期间 MMPV 开帐 &#xff08;下篇见&#xff09;

K-【学习Diffusers 四】 读取模型参数 bin格式、safetensors格式

该操作多用于推理 safetensors格式的参数读取方法 1 拿到pipeline中的unet的办法 unet pipeline.pipe.unet 2 safetensors格式文件的参数读取方法 state_dict safetensors.torch.load_file(args.model_id, device"cpu") unet.load_state_dict(state_dict) # 读入…

随心玩玩(十二)通义千问——LLM大模型微调

写在前面&#xff1a;使劲的摸鱼&#xff0c;摸到的鱼才是自己的~ 文章目录 简介环境配置模型加载jupyter远程配置快速使用微调示例部署方案总结附录&#xff1a; ReAct Prompting 示例准备工作一&#xff1a;样例问题、样例工具准备工作二&#xff1a;ReAct 模版步骤一&#x…

MySQL:DML数据操作语言(添加,删除,修改),DDL数据查询语言(条件查询,分组查询,排序查询,分页查询)

目录 1.DML&#xff08;数据操作语言&#xff09;1.添加数据2.修改数据3.删除数据 2.DQL(数据查询语言)1.DQL-语法2.基本查询3.条件查询(WHERE)1.语法&#xff1a;2.条件&#xff1a;3.案例: 4.聚合函数1.介绍2.常见聚合函数3.语法4.案例 5.分组查询&#xff08;GROUP BY&#…

物联网通讯协议NB-lot和LoRa差异分析

像把大象装冰箱一样&#xff0c;物联网&#xff0c;万物互联也是要分步骤的。 一、感知层(信息获取层)&#xff0c;即利用各种传感器等设备随时随地获取物体的信息; 二、网络层(信息传输层)&#xff0c;通过各种电信网络与互联网的融合&#xff0c;将物体的信息实时准确地传递…

力扣LCR 166. 珠宝的最高价值(java 动态规划)

Problem: LCR 166. 珠宝的最高价值 文章目录 解题思路思路解题方法复杂度Code 解题思路 思路 改题目与本站64题实质上是一样的&#xff0c;该题目在64题的基础上将求取最小路径和改成了求取最大路径和。具体实现思路如下&#xff1a; 1.定义一个int类型的二维数组dp大小为给定…

17- Echarts 配置系列之:单轴 singleAxis

singleAxis&#xff1a; 用于展示只有一个数据维度的数据。它通常用于展示时间序列数据或者数值序列数据。 对于单轴的应用和绘制&#xff0c;其实就相当于我们平时的直角坐标系少一个 X 或者 Y &#xff0c;然后进行图形绘制。 注意&#xff1a; 1.在使用单轴时&#xff0…

1.10号io网络

信号量&#xff08;信号灯集&#xff09; 1> 信号灯集主要完成进程间同步工作&#xff0c;将多个信号灯&#xff0c;放在一个信号灯集中&#xff0c;每个信号灯控制一个进程 2> 每个灯维护了一个value值&#xff0c;当value值等于0时&#xff0c;申请该资源的进程处于阻…

【Python学习】Python学习13-日期和时间

目录 【Python学习】Python学习13-日期和时间 前言通过time 获取时间戳时间元组获取当前时间&#xff0c;格式化时间格式化时间转换python中时间日期格式化符号获取日历Time 模块日历&#xff08;Calendar&#xff09;模块其他模块参考 文章所属专区 Python学习 前言 本章节主…

小马识途:十个营销故事 启发营销思路

在营销过程中&#xff0c;优势是相对的&#xff0c;只有凭借着客观的营销环境创造优势才能够取胜市场。在企业营销中&#xff0c;狗猛酒酸的案例比比皆是。接下来&#xff0c;就与小马识途一起来看看十个经典的营销故事吧&#xff01; 一、摩托车公司 有家德国摩托车公司&…

SQL优化小技巧

在表中建⽴索引&#xff0c;优先考虑 where group by 使⽤到的字段。 查询时尽量避免使⽤select * &#xff0c;只查询需要⽤到的字段。 避免在where⼦句中使⽤关键字两边都是%的模糊查询&#xff0c;尽量在关键字后使⽤模糊查询。 尽量避免在where⼦句中使⽤IN 和NOT IN。 …

【排序】快速排序(C语言实现)

文章目录 前言1. Hoare思想2. 挖坑法3. 前后指针法4. 三路划分5. 快速排序的一些小优化5.1 三数取中常规的三数取中伪随机的三数取中 5.2 小区间优化 6. 非递归版本的快排7. 快速排序的特性总结 前言 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其…

【开源项目】轻量元数据管理解决方案——Marquez

大家好&#xff0c;我是独孤风。 又到了本周的开源项目推荐。最近推荐的元数据管理项目很多&#xff0c;但是很多元数据管理平台的功能复杂难用。 那么有没有轻量一点的元数据管理项目呢&#xff1f; 今天为大家推荐的开源项目&#xff0c;就是一个轻量级的元数据管理工具。虽然…

Linux入门攻坚——12、Linux网络属性配置相关知识2

CentOS 7网络属性配置&#xff1a; 传统命名机制&#xff1a;以太网eth[0,1,2,...]&#xff0c;wlan[0,1,2...] 可预测功能的命名机制&#xff1a; udev支持多种不同的命名方案&#xff1a; Firmware &#xff0c;拓扑结构 在对待设备文件这块&#xff0c;Linux改…

【大厂算法面试冲刺班】day2:合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 递归 class Solution {public ListNode mergeTwoLists(ListNode l1, ListNode l2) {if (l1 null) {return l2;}else if (l2 null) {return l1;}else if (l1.val < l2.…

人生重开模拟器(c语言)

前言&#xff1a; 人生重开模拟器是前段时间非常火的一个小游戏&#xff0c;接下来我们将一起学习使用c语言写一个简易版的人生重开模拟器。 网页版游戏&#xff1a; 人生重开模拟器 (ytecn.com) 1.实现一个简化版的人生重开模拟器 &#xff08;1&#xff09; 游戏开始的时…

云HIS系统源码,基层卫生HIS系统,云端SaaS模式多医院版

系统介绍&#xff1a; 基层卫生健康云HIS系统采用云端SaaS服务的方式提供&#xff0c;使用用户通过浏览器即能访问&#xff0c;无需关注系统的部署、维护、升级等问题&#xff0c;系统充分考虑了模板化、配置化、智能化、扩展化等设计方法&#xff0c;覆盖了基层医院的主要工作…