Flutter BottomSheet 三段式拖拽

这篇具有很好参考价值的文章主要介绍了Flutter BottomSheet 三段式拖拽。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前面倒是有讲过Android原生的BottomSheetBehavior,使用场景还是蛮多的,最近在用Flutter做一款地图App,有用到BottomSheet的功能,但是 Flutter 自带的BottomSheet有点拉,只能显示和隐藏销毁,不支持折叠为最小高度状态也不支持三段式拖动,那就自己撸一个吧:

追踪 BottomSheet

既然是基于系统的BottomSheet ,不妨来看看sdk的实现方式,正常来讲,显示一个BottomSheet,可以通过showBottomSheet 来触发,或者给Scaffold配置bottomSheet属性,查看源码可以看到Scaffold.of(context).showBottomSheet,内部是创建了一个_StandardBottomSheet,继续追踪发现Widget其实是通过AnimatedBuilder来实现内容高度的扩展,其内部维护了一个BottomSheet。

简单阅读下BottomSheet源码,重点就在于 GestureDetector 的垂直方向上的手势回调 onVerticalDragUpdate 、以及onVerticalDragEnd,拖动位置更新、惯性滑动以及销毁,核心都在这了。
Flutter BottomSheet 三段式拖拽,flutter,BottomSheet,BottomSheet三段式,拖拽

系统默认实现效果

  • 拖拽速度大于某一个像素阀值时,销毁。
  • 拖拽位置小于总高度的一半时,销毁。

保留这一份默认效果,对于想使用默认效果的同学,不做任何额外配置即可。

Flutter BottomSheet 三段式拖拽,flutter,BottomSheet,BottomSheet三段式,拖拽

准备要实现的功能点:

  1. 三段式: 基于SDK的BottomSheet ,可扩展为完全展开、中间状态、折叠状态;
  2. 阻尼、惯性滑动: 支持配置最小滑动偏移量;
  3. 保持状态,支持Peek状态: 以最小高度显示BottomSheet;
  4. 打破 showBottomSheet 限制: 兼容系统默认的弹出方式,亦可当作正常的Widget使用,脱离showBottomSheet。

定义三段式状态:BottomSheetBehavoir

  • EXPANDED 完全展开
  • HALF 中间状态,介于EXPANDED与PEEK之间
  • PEEK 以一个最小高度展示
  • HIDDEN 完全隐藏,即销毁,系统默认效果

开启三段式,我们还需要配置一个约束条件,即BottomSheet的最大高度和最小高度 BoxConstraints:

  • 最小高度
    HALF模式下
    如果提供的 Constraints minHeight 小于最大高度的一半,则取后者,防止位置错乱!
var peekThreshold = enableHalf
     ? min(_childHeight / 2, constraints.minHeight) / _childHeight
     : constraints.minHeight / _childHeight;

阀值定义

  • 拖拽滚动阀值,大于此值,才允许滑动
    const double _offsetThreshold = 32.0;
  • 展开时最大高度 阀值
    const double _maxThreshold = 1.0;
  • 中间状态阀值
    const double _halfThreshold = 0.5;

当拖拽结束时,如果拖拽偏移量小于此阀值,则恢复状态,这里有个麻烦的点是需要根据用户拖拽方向来判断,是向上还是向下拖动。
方向判断可以在 _handleDragStart 回调时记录初始偏移量startY,_handleDragEnd 时计算开始和结束的差值

/// 偏移量
var offset = updateY-startY ;
/// 当前动画值
 var value = widget.animationController!.value;
 late double toValue;
 late BottomSheetBehavior mode;

offset<0 为向上滑动,反之 向下滑动。接下来需要根据滚动阀值来更新BottomSheet状态。

1. 未达到滚动阀值,恢复状态

  • 向上滑动,恢复BottomSheet状态: Expanded / Half / Peek
if (value >= _maxThreshold) {
   // 处于Expand状态,恢复
   toValue = _maxThreshold;
   mode = BottomSheetBehavior.EXPANDED;
 } else if (value > _halfThreshold && enableHalf) {
   // 处于Half,恢复
   toValue = _halfThreshold;
   mode = BottomSheetBehavior.HALF;
 } else {
   toValue = peekThreshold;
   mode = BottomSheetBehavior.PEEK;
 }
  • 向下滑动,恢复BottomSheet状态: Expanded / Half / Peek
if (value > _halfThreshold) {
   // 处于Expand状态,恢复
   toValue = _maxThreshold;
   mode = BottomSheetBehavior.EXPANDED;
 } else if (value > peekThreshold && enableHalf) {
   // 处于Half,恢复
   toValue = _halfThreshold;
   mode = BottomSheetBehavior.HALF;
 } else {
   toValue = peekThreshold;
   mode = BottomSheetBehavior.PEEK;
 }

2. 达到滚动阀值,更新状态

  • 向上滑动,更新BottomSheet状态: Expanded / Half / Peek
if (value > _halfThreshold) {
   toValue = _maxThreshold;
   mode = BottomSheetBehavior.EXPANDED;
 } else if (value > peekThreshold) {
   toValue = enableHalf ? _halfThreshold : _maxThreshold;
   mode = enableHalf ? BottomSheetBehavior.HALF : BottomSheetBehavior.EXPANDED;
 } else {
   toValue = peekThreshold;
   mode = BottomSheetBehavior.PEEK;
 }
  • 向下滑动,更新BottomSheet状态: Half / Peek
if (value > _halfThreshold) {
  toValue = enableHalf ? _halfThreshold : peekThreshold;
  mode = enableHalf ? BottomSheetBehavior.HALF : BottomSheetBehavior.PEEK;
} else {
  toValue = peekThreshold;
  mode = BottomSheetBehavior.PEEK;
}

以上,我们获取到了开始讲到的AnimatedBuilder的 动画值以及变化量,在**_handleDragEnd**中可以通过animateTo平滑的过渡BottomSheet状态

/// 以动画的形式fly
void animateTo(double to) {
  widget.animationController!.animateTo(
    to,
    curve: Curves.linearToEaseOut,
    duration: animateDuration,
  );
}
  • 另外,至于BottomSheet的最新的状态回调,最好是在动画结束后再通知给调用者,以免更新状态期间build重绘!
Future.delayed(animateDuration, () => widget.onBehaviorChanged?.call(mode));

至此,既保留了flutter默认的BottomSheet效果,又扩展了三段式,当然,调用方式和系统BottomSheet一模一样,另外还可以像普通Widget一样来使用哦*
Just Do It :

bottom_sheet_plus: ^0.0.1

来看看最终的效果吧

项目效果

Demo文章来源地址https://www.toymoban.com/news/detail-707385.html

到了这里,关于Flutter BottomSheet 三段式拖拽的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Verilog基础:三段式状态机与输出寄存

    相关阅读 Verilog基础 https://blog.csdn.net/weixin_45791458/category_12263729.html         对于Verilog HDL而言,有限状态机(FSM)是一种重要而强大的模块,常见的有限状态机书写方式可以分为一段式,二段式和三段式,笔者强烈建议使用三段式因为这样能使状态机逻辑清晰且易于维护。    

    2024年02月04日
    浏览(43)
  • 三段式电流保护与自动重合闸MATLAB仿真模型

    微 ❤ 关注“电气仔推送”获得资料(专享优惠) 前加速、后加速的区别: 前加速是保护装置不判别是永久性故障还是瞬时故障,直接跳闸,然后经重合闸装置来纠正;后加速是保护装置是先判别故障类型有选择性跳闸 以下只叙述后加速的相关内容,前加速不在赘述!!!

    2024年02月02日
    浏览(37)
  • 【附源码】基于fpga的自动售货机(三段式状态机)

    目录 1、VL38 自动贩售机1 题目介绍 思路分析 代码实现 仿真文件 2、VL39 自动贩售机2 题目介绍: 题目分析 代码实现 仿真文件 3、状态机基本知识         设计一个自动贩售机,输入货币有三种,为0.5/1/2元,饮料价格是1.5元,要求进行找零,找零只会支付0.5元。 ps:   

    2024年02月01日
    浏览(47)
  • Verilog写状态机的三种描述方式之三段式

    状态机的设计思路: 一是从状态机变量入手,分析各个状态的输入、状态转移和输出; 二是先确定电路的输出关系,再回溯规划每个状态的条件、输入等; 状态机的三要素是状态、输入和输出 , 根据状态机状态是否和输入条件相关,可以分为Moore型状态机(与输入无关)和

    2024年02月14日
    浏览(44)
  • 【零基础玩转BLDC系列】无刷直流电机无位置传感器三段式启动法详细介绍及代码分享

    无刷直流电动机基本转动原理等内容请参考《基于霍尔传感器的无刷直流电机控制原理》、《基于反电动势过零检测法的无刷直流电机控制原理》与《以GD32F30x为例定时器相关功能详解》,BLDC基本原理及基础知识本篇不再赘述。 直流无刷电机由于定子绕组的反电动势与电机的

    2023年04月08日
    浏览(91)
  • Flutter:功能型组件(3)- 拖拽组件、缩放平移组件

    拖拽组件包含 Draggable 、 LongPressDraggable 和 DragTarget 。 Draggable 、 LongPressDraggable 为可拖拽的组件, LongPressDraggable 继承自 Draggable ,因此用法和 Draggable 完全一样,唯一的区别就是 LongPressDraggable 触发拖动的方式是长按,而 Draggable 触发拖动的方式是按下。 DragTarget 为拖拽组件的

    2024年02月08日
    浏览(43)
  • 【Flutter】Flutter 如何使用 flutter_swiper

    在移动应用开发中,轮播图是一种常见的 UI 元素,它可以用来展示一系列的图片或者内容。在 Flutter 中,我们可以使用 flutter_swiper 这个库来创建轮播图。那么在 Flutter 这个强大的移动应用开发框架中,我们如何使用 flutter_swiper 呢? 如果你想深入学习 Flutter,掌握更多的技巧

    2024年02月09日
    浏览(48)
  • Flutter学习四:Flutter开发基础(六)调试Flutter应用

    目录 0 引言 1 调试Flutter应用 1.1 日志与断点 1.1.1 debugger() 声明 1.1.2 print和debugPrint 1.1.3 调试模式、中间模式、发布模式 1.1.4 断点 1.2 调试应用程序层 1.2.1 转储Widgets树 1.2.2  转储渲染树 1.2.3 转储Layer树 1.2.4 转储语义树 1.2.5 调度(打印帧的开始和结束) 1.2.6 可视化调试

    2024年02月12日
    浏览(56)
  • Flutter 笔记 | Flutter 动画

    为了方便开发者创建动画,不同的UI系统对动画都进行了一些抽象, Flutter中也对动画进行了抽象,主要涉及 Animation、Curve、Controller、Tween 这四个角色,它们一起配合来完成一个完整动画,下面我们一一来介绍它们。 1. Animation Animation 是一个抽象类,它本身和UI渲染没有任何关

    2024年02月07日
    浏览(47)
  • 【Flutter】Flutter简介

    Flutter是Google开发的一款用于构建高性能、高保真移动应用程序的开源UI工具包。它允许开发人员使用Dart语言来构建跨平台的移动应用程序,并提供了丰富的UI组件、动画效果和手势识别等功能。 以下是Flutter入门的一些详细介绍: Flutter概述 Flutter是一个基于Dart语言的跨平台移

    2024年02月10日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包