当前位置: 首页 > news >正文

Flutter-底部弹出框(Widget层级)

需求
  • 支持底部弹出对话框。
  • 支持手势滑动关闭。
  • 支持在widget中嵌入引用。
  • 支持底部弹出框弹出后不影响其他操作。
  • 支持弹出框中内容固定头部和下面列表时,支持触摸头部并在列表不在头部的时候支持滑动关闭
简述

通过上面的需求可知,就是在界面中可以支持底部弹出一个弹出框,但是又不影响除了这个弹出框外其他操作,同时支持手势滑动关闭。想到这里我们其实会想到一个控件DraggableScrollableSheet,Flutter提供一种可以支持在widget中引入的底部弹出布局,同时不影响其他的操作,所以我就使用这个控件测试了下,发现一个问题,就是当底部弹出框内容为上面有个头部,底部是个列表时,每次都需要列表滑动到顶部的时候才可以手势滑动关闭,所以需要支持触摸顶部布局也支持手势滑动关闭,所以在此控件上做一个修改。

效果

bottom_sheet.gif

代码如下
`import 'package:flutter/material.dart';/// 底部弹出Widget
/// 1、支持手势下拉关闭
/// 2、支持动画弹出收起
/// 3、支持弹出无法关闭
class DragBottomSheetWidget extends StatefulWidget {DragBottomSheetWidget({required Key key,required this.builder,this.duration,this.childHeightRatio = 0.8,this.onStateChange,}) : super(key: key);Function(bool)? onStateChange;final double childHeightRatio;final Duration? duration;final ScrollableWidgetBuilder builder;@overrideState<DragBottomSheetWidget> createState() => DragBottomSheetWidgetState();
}class DragBottomSheetWidgetState extends State<DragBottomSheetWidget>with TickerProviderStateMixin {final controller = DraggableScrollableController();//是否可以关闭bool isCanClose = true;//是否展开bool isExpand = false;double verticalDistance = 0;@overridevoid initState() {super.initState();}@overridevoid dispose() {controller.dispose();super.dispose();}Future show({bool isCanClose = true}) {return controller.animateTo(1,duration: widget.duration ?? const Duration(milliseconds: 200),curve: Curves.linear).then((value) {if (!isCanClose) {setState(() {this.isCanClose = isCanClose;});}});}void hide() {controller.animateTo(0,duration: widget.duration ?? const Duration(milliseconds: 200),curve: Curves.linear,);}void _dragJumpTo(double y) {var size = y / MediaQuery.of(context).size.height;controller.jumpTo(widget.childHeightRatio - size);}void _dragEndChange() {controller.size >= widget.childHeightRatio / 2? controller.animateTo(1,duration: widget.duration ?? const Duration(milliseconds: 200),curve: Curves.linear,): hide();}@overrideWidget build(BuildContext context) {return NotificationListener<DraggableScrollableNotification>(onNotification: (notification) {if (notification.extent == widget.childHeightRatio) {if (!isExpand) {isExpand = true;widget.onStateChange?.call(true);}} else if (notification.extent < 0.00001) {if (isExpand) {isExpand = false;widget.onStateChange?.call(false);}}return true;},child: DraggableScrollableSheet(initialChildSize: isCanClose && !isExpand ? 0 : widget.childHeightRatio,minChildSize: isCanClose ? 0 : widget.childHeightRatio,maxChildSize: widget.childHeightRatio,expand: true,snap: true,controller: controller,builder: (BuildContext context, ScrollController scrollController) {return GestureDetector(behavior: HitTestBehavior.translucent,onVerticalDragDown: (details) {verticalDistance = 0;},onVerticalDragUpdate: (details) {verticalDistance += details.delta.dy;_dragJumpTo(verticalDistance);},onVerticalDragEnd: (details) {_dragEndChange();},child: widget.builder.call(context, scrollController),);},),);}
}

使用

import 'package:flutter/material.dart';
import 'package:flutter_xy/widgets/xy_app_bar.dart';
import 'package:flutter_xy/xydemo/darg/drag_bottom_sheet_widget.dart';class DragBottomSheetPage extends StatefulWidget {const DragBottomSheetPage({super.key});@overrideState<DragBottomSheetPage> createState() => _DragBottomSheetPageState();
}class _DragBottomSheetPageState extends State<DragBottomSheetPage> {final GlobalKey<DragBottomSheetWidgetState> bottomSheetKey =GlobalKey<DragBottomSheetWidgetState>();bool isExpand = false;@overrideWidget build(BuildContext context) {return Scaffold(backgroundColor: Colors.deepPurple.withAlpha(50),appBar: XYAppBar(title: "底部弹出布局",backgroundColor: Colors.transparent,titleColor: Colors.white,onBack: () {Navigator.pop(context);},),body: Stack(children: [Positioned(top: 0,child: Column(mainAxisSize: MainAxisSize.max,children: [InkWell(onTap: () {if (isExpand) {bottomSheetKey.currentState?.hide();} else {bottomSheetKey.currentState?.show();}},child: Container(width: MediaQuery.of(context).size.width - 60,alignment: Alignment.center,height: 50,margin: const EdgeInsets.symmetric(horizontal: 30),decoration: BoxDecoration(borderRadius: BorderRadius.circular(32),color: Colors.deepPurple,),child: Text(isExpand ? "收起" : "弹出",style: const TextStyle(fontSize: 16,fontWeight: FontWeight.w600,color: Colors.white,),),),),const SizedBox(height: 20),],)),Positioned(child: DragBottomSheetWidget(key: bottomSheetKey,onStateChange: (isExpand) {setState(() {this.isExpand = isExpand;});},builder:(BuildContext context, ScrollController scrollController) {return Container(alignment: Alignment.topLeft,child: Stack(children: [Container(height: 50,decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(16),topRight: Radius.circular(16)),color: Colors.yellow,),),Expanded(child: Container(margin: const EdgeInsets.only(top: 50),child: ListView.builder(itemCount: 500,controller: scrollController,itemBuilder: (context, index) {return index % 2 == 0? Container(height: 100,width: MediaQuery.of(context).size.width,color: Colors.red,): Container(height: 100,width: MediaQuery.of(context).size.width,color: Colors.blue,);},),),),],),);},),),],),);}
}

完整代码见:https://github.com/yixiaolunhui/flutter_xy

相关文章:

Flutter-底部弹出框(Widget层级)

需求 支持底部弹出对话框。支持手势滑动关闭。支持在widget中嵌入引用。支持底部弹出框弹出后不影响其他操作。支持弹出框中内容固定头部和下面列表时&#xff0c;支持触摸头部并在列表不在头部的时候支持滑动关闭 简述 通过上面的需求可知&#xff0c;就是在界面中可以支持…...

聚焦两会:数字化再加速,VR全景助力制造业转型

近年来&#xff0c;随着信息技术、人工智能、VR虚拟现实等新兴技术的不断涌现&#xff0c;数字化正日益成为推动当今经济发展的新驱动力。在不久前的两会上&#xff0c;数字化经济和创新技术再度成为热门话题&#xff1a; 国务院总理李强作政府工作报告&#xff1a; 要深入推…...

数据挖掘之关联规则

“啤酒和尿布的荣誉” 概念 项 item&#xff1a;单个的事物个体 &#xff0c;I{i1,i2…im}是所有项的集合&#xff0c;|I|m是项的总数项集&#xff08;item set)/模式&#xff08;pattern)&#xff1a;项的集合&#xff0c;包含k个项的项集称为k-项集数据集(data set)/数据库…...

java:java.util.BitSet对象的Jackson序列化和反序列化实现

java.util.BitSet是个非常方便的比特位数据存储和操作类&#xff0c;一个 bit 具有2个值&#xff1a;0和1&#xff0c;正好可以用来表示 false 和 true&#xff0c;适用于判断“数据是否存在”的场景。 但是&#xff0c;这个从JDK1.0版本就存在的类&#xff0c;Jackson,Fastjso…...

Go语言学习01-基本程序结构

文章目录 Go语言学习01-基本程序结构基本程序结构应用程序入口退出返回值编写测试程序快速设置连续值基本数据类型类型的预定义值指针类型运算符算数运算符比较运算符用 比较数组 逻辑运算符位运算符&^ 按位 置零 Go语言学习01-基本程序结构 基本程序结构 package main …...

rundeck k8s部署踩坑

1、镜像启动后原来的定时任务无法运行 参考&#xff1a; https://github.com/rundeck/rundeck/issues/4275 https://stackoverflow.com/questions/60942785/env-variable-for-rundeck-feature-joblifecycleplugin-enabled/60959605#60959605 结论&#xff1a; &#xff08;1&…...

每天学习几道面试题|Kafka(二)架构设计类

文章目录 1. Kafka 是如何保证高可用性和容错性的&#xff1f;2. Kafka 的存储机制是怎样的&#xff1f;它是如何处理大量数据的&#xff1f;3. Kafka 如何处理消费者的消费速率低于生产者的生产速率&#xff1f;4. Kafka 集群中的 Controller 是什么&#xff1f;它的作用是什么…...

Spring 实现 OAuth2 授权之解决方案

Spring Security OAuth2 - 已经废弃的项目 早期的Spring 使用 Spring Security OAuth2 实现 OAuth 2.0 的认证服务器和资源服务器。OAuth2是一个授权框架,它允许第三方应用获取有限的访问权限,而无需获取用户的账号和密码等敏感信息。通过这种方式,OAuth2协议实现了安全的用…...

el-select使用filterable下拉无法关闭得问题

这里推荐一个前端框架 sakuya / SCUI&#xff0c;他里面有个formTable&#xff0c;可以解决很多订单明细保存得问题。基本沿用element-plus的前端使用模式&#xff0c;让表单表格变的非常容易。 这个的供应商插件&#xff0c;当使用filterable后&#xff0c;点击表格重的选项&…...

基于javaweb(springboot)城市地名地址信息管理系统设计和实现

基于javaweb(springboot)城市地名地址信息管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言…...

vue iframe实现父页面实时调用子页面方法和内容

父页面标签添加鼠标按下事件 父页方法中建立iframe通信 实时调用子页面方法 实时更改子页面文本内容...

HarmonyOS ArkTS 开发基础/语言

目录 一、ArkUI (方舟开发框架) 概述 1.1 基本概念 1.2 两种开发范式 1.3 不同应用类型支持的开发范式 二、ArkTS 声明式开发范式 2.1 开发能力 2.2 整体架构 三、ArkTS 基础类型 3.1 Any 类型 3.2 数字类型 3.3 字符串类型 3.4 布尔类型 3.5 联合类型 3.6 数组类…...

AI大模型学习

AI大模型学习 在当前技术环境下&#xff0c;AI大模型学习不仅要求研究者具备深厚的数学基础和编程能力&#xff0c;还需要对特定领域的业务场景有深入的了解。通过不断优化模型结构和算法&#xff0c;AI大模型学习能够不断提升模型的准确性和效率&#xff0c;为人类生活和工作…...

2024年【T电梯修理】考试内容及T电梯修理作业考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 T电梯修理考试内容根据新T电梯修理考试大纲要求&#xff0c;安全生产模拟考试一点通将T电梯修理模拟考试试题进行汇编&#xff0c;组成一套T电梯修理全真模拟考试试题&#xff0c;学员可通过T电梯修理作业考试题库全真…...

2.vscode 配置python开发环境

vscode用着习惯了,也不想再装别的ide 1.安装vscode 这一步默认已完成 2.安装插件 搜索插件安装 3.选择调试器 Ctrl Shift P&#xff08;或F1&#xff09;&#xff0c;在打开的输入框中输入 Python: Select Interpreter 搜索&#xff0c;选择 Python 解析器 选择自己安…...

[蓝桥杯 2015 省 B] 生命之树

题目链接 [蓝桥杯 2015 省 B] 生命之树 题目描述 在 X 森林里&#xff0c;上帝创建了生命之树。 他给每棵树的每个节点&#xff08;叶子也称为一个节点&#xff09;上&#xff0c;都标了一个整数&#xff0c;代表这个点的和谐值。 上帝要在这棵树内选出一个节点集合 S S S&…...

为什么Hashtable不允许插入nuIl键和null值?

1、典型回答 浅层次的来回答这个问题的答案是&#xff0c;JDK 源码不支持 Hashtable 插入 value 值为 null&#xff0c;如以下 JDK 源码所示&#xff1a; 也就是 JDK 源码规定了&#xff0c;如果你给 Hashtable 插入 value 值为 null 就会抛出空指针异常。 并且看上面的 JDK …...

【WPF应用4】WPF界面对象编辑

简介 WPF&#xff08;Windows Presentation Foundation&#xff09;是.NET框架的一部分&#xff0c;它为开发人员提供了一个用于构建桌面应用程序用户界面的强大平台。WPF界面对象编辑是指在WPF应用程序中创建、设计和修改用户界面元素的过程。这些界面对象不仅包括基本的控件…...

js数组去重常见方法

简单数组 1、使用filter()方法&#xff1a;通过filter()方法遍历数组&#xff0c;返回仅包含首次出现的元素的新数组。 const arr [1, 2, 3, 4, 2, 3, 5]; const list arr.filter((item, index) > arr.indexOf(item) index); console.log(list); // [1, 2, 3, 4, 5]2、…...

【Java Web基础】一些网页设计基础(二)

文章目录 1. Bootstrap导航栏设计1.1 代码copy与删减效果1.2 居中属性与底色设置1.3 占不满问题分析1.4 字体颜色、字体大小、字体间距设置1.5 修改超链接hover颜色&#xff0c;网站首页字体颜色 1. Bootstrap导航栏设计 1.1 代码copy与删减效果 今天设计导航栏&#xff0c;直…...

Qwen3-VL-4B Pro从零开始:基于Streamlit的现代化WebUI定制化部署

Qwen3-VL-4B Pro从零开始&#xff1a;基于Streamlit的现代化WebUI定制化部署 1. 项目概述 想不想让电脑不仅能看懂图片&#xff0c;还能跟你聊图片里的内容&#xff1f;Qwen3-VL-4B Pro就是这样一个神奇的工具。它基于阿里通义千问的最新视觉语言模型&#xff0c;能够理解图片…...

浮点数运算中的那些坑:IEEE 754标准下的精度丢失与解决方案

浮点数运算中的那些坑&#xff1a;IEEE 754标准下的精度丢失与解决方案 第一次在财务系统中看到0.10.2≠0.3时&#xff0c;我以为是代码写错了。直到查阅资料才发现&#xff0c;这是计算机科学中一个经典的浮点数精度问题——就像用刻度不精确的尺子测量&#xff0c;结果总会存…...

《信息系统项目管理师教程(第4版)》监控项目工作(监控过程组)知识结构+10道真题

《信息系统项目管理师教程&#xff08;第4版&#xff09;》监控项目工作&#xff08;监控过程组&#xff09;知识结构及真题一、监控项目工作&#xff08;监控过程组&#xff09;知识结构1. 监控项目工作概述定义&#xff1a;跟踪、审查和报告项目进展&#xff0c;以实现项目管…...

AMD Ryzen调试工具:专业级硬件性能优化指南

AMD Ryzen调试工具&#xff1a;专业级硬件性能优化指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitcode.com/…...

终极Python大麦抢票神器:告别手动抢票的完整自动化指南

终极Python大麦抢票神器&#xff1a;告别手动抢票的完整自动化指南 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 还在为抢不到心仪的演唱会门票而烦恼吗&#xff1f;DamaiHelper是一个基于Pyth…...

终极指南:3步掌握安卓虚拟定位技术,FakeLocation实现应用级位置隔离

终极指南&#xff1a;3步掌握安卓虚拟定位技术&#xff0c;FakeLocation实现应用级位置隔离 【免费下载链接】FakeLocation Xposed module to mock locations per app. 项目地址: https://gitcode.com/gh_mirrors/fak/FakeLocation 在数字化时代&#xff0c;位置信息已成…...

K8s 1.36 新特性深度解析:服务网格与零信任集成(生产级配置)

K8s 1.36 新特性深度解析&#xff1a;服务网格与零信任集成&#xff08;生产级配置&#xff09; 前言&#xff1a;K8s 1.36 被称为“云原生安全网络里程碑”版本&#xff0c;核心突破集中在「服务网格原生化」和「零信任落地」两大板块——彻底解决了过去服务网格“资源占用高、…...

基于RVC模型的实时合唱系统:单人模拟多人合唱效果

基于RVC模型的实时合唱系统&#xff1a;单人模拟多人合唱效果 你有没有想过&#xff0c;一个人也能唱出气势磅礴的合唱效果&#xff1f;以前这可能需要一个录音棚和一群专业歌手&#xff0c;但现在&#xff0c;借助AI技术&#xff0c;一个人、一台电脑就能轻松实现。今天要聊的…...

福禄克DSX-602认证分析仪科普小知识

福禄克&#xff08;FLUKE&#xff09;DSX-602 是一款专业级的铜缆认证分析仪&#xff0c;专为 **Cat 6A&#xff08;超六类&#xff09;** 及以下网线的工程验收、性能认证和故障诊断设计。一、核心定位与参数 测试范围&#xff1a;Cat 3/Class C ~ Cat 6A/Class EA 双绞线铜缆…...

UniApp实战:Android原生插件实现动态时间水印踩坑全记录(附完整代码)

UniApp实战&#xff1a;Android原生插件实现动态时间水印的深度优化方案 在移动应用开发中&#xff0c;视频处理一直是技术难点之一&#xff0c;特别是需要实时添加动态时间水印的场景。本文将分享在UniApp中开发Android原生插件时&#xff0c;如何高效实现动态时间水印功能&am…...