如何在 Flutter 中实现可拖动的底部弹出框

embedded/2024/10/20 5:20:43/

在 Flutter 开发中,底部弹出框(Bottom Sheet)是一种常见的 UI 组件,通常用于显示一些额外的操作选项或详细信息。在这篇文章中,我将介绍一个自定义的 DragBottomSheetWidget 组件,它不仅支持手势拖动关闭,还可以通过动画进行弹出和收起。

组件功能概述

DragBottomSheetWidget 是一个支持手势拖动和动画效果的底部弹出框组件。它具有以下几个主要功能:

  1. 手势下拉关闭:用户可以通过向下拖动来关闭底部弹出框。
  2. 动画弹出收起:支持平滑的动画效果,弹出或收起时更加自然。
  3. 弹出后无法关闭:在特定场景下,弹出框可以设置为无法通过手势关闭。
代码解析

首先,我们来看一下 DragBottomSheetWidget 的代码实现:

import 'package:flutter/material.dart';class DragBottomSheetWidget extends StatefulWidget {const DragBottomSheetWidget({super.key,required this.builder,this.duration = const Duration(milliseconds: 200),this.childHeightRatio = 0.8,this.onStateChange,});final Function(bool)? onStateChange;final double childHeightRatio;final Duration duration;final ScrollableWidgetBuilder builder;State<DragBottomSheetWidget> createState() => DragBottomSheetWidgetState();
}class DragBottomSheetWidgetState extends State<DragBottomSheetWidget> {final DraggableScrollableController controller =DraggableScrollableController();final ValueNotifier<bool> isExpandNotifier = ValueNotifier<bool>(false);double verticalDistance = 0;void initState() {super.initState();}void dispose() {controller.dispose();isExpandNotifier.dispose();super.dispose();}Future<void> show({bool isCanClose = true}) async {try {await controller.animateTo(1,duration: widget.duration,curve: Curves.linear,);if (!isCanClose) {isExpandNotifier.value = true;}} catch (e) {print('Error animating to full size: $e');}}void hide() {controller.animateTo(0,duration: widget.duration,curve: Curves.linear,);}void _dragJumpTo(double y) {final size = y / MediaQuery.sizeOf(context).height;final jumpToValue = widget.childHeightRatio - size;controller.jumpTo(jumpToValue.clamp(0, widget.childHeightRatio));}void _dragEndChange(DragEndDetails dragEndDetails) {if (controller.size >= widget.childHeightRatio / 2) {controller.animateTo(1,duration: widget.duration,curve: Curves.linear,);} else {hide();}}Widget build(BuildContext context) {return NotificationListener<DraggableScrollableNotification>(onNotification: (notification) {isExpandNotifier.value = notification.extent == widget.childHeightRatio;widget.onStateChange?.call(isExpandNotifier.value);return true;},child: ValueListenableBuilder<bool>(valueListenable: isExpandNotifier,builder: (context, isExpand, child) {return DraggableScrollableSheet(initialChildSize: !isExpand ? 0 : widget.childHeightRatio,minChildSize: 0,maxChildSize: widget.childHeightRatio,expand: true,snap: true,controller: controller,builder: (BuildContext context, ScrollController scrollController) {return _DragHandler(onDragDown: () => verticalDistance = 0,onDragUpdate: (details) {verticalDistance += details.delta.dy;_dragJumpTo(verticalDistance);},onDragEnd: _dragEndChange,child: widget.builder(context, scrollController),);},);},),);}
}class _DragHandler extends StatelessWidget {const _DragHandler({required this.onDragDown,required this.onDragUpdate,required this.onDragEnd,required this.child,});final VoidCallback onDragDown;final GestureDragUpdateCallback onDragUpdate;final GestureDragEndCallback onDragEnd;final Widget child;Widget build(BuildContext context) {return GestureDetector(behavior: HitTestBehavior.translucent,onVerticalDragDown: (_) => onDragDown(),onVerticalDragUpdate: onDragUpdate,onVerticalDragEnd: onDragEnd,child: child,);}
}
核心功能解读
  1. 控制器与状态管理:组件内部使用了 DraggableScrollableController 来控制弹出框的显示状态,ValueNotifier<bool> 用于监听弹出框的展开与收起状态。

  2. 显示与隐藏show 方法通过 animateTo 将弹出框平滑展开至全屏,而 hide 方法则将其收起至不可见状态。

  3. 手势控制:通过 _dragJumpTo 方法和 _dragEndChange 方法,组件可以响应用户的手势操作,决定弹出框的滑动与状态变化。

  4. Builder 模式:通过 builder 回调,开发者可以自定义弹出框中的内容,满足不同场景的需求。

使用场景

DragBottomSheetWidget 适用于需要在屏幕底部弹出一些交互式内容的场景,如表单输入、操作选项等。通过手势控制和动画效果,可以为用户提供更加流畅和直观的操作体验。

结语

自定义 DragBottomSheetWidget 组件不仅增强了 Flutter 的弹出框功能,还为用户提供了更多的交互可能性。如果你正在开发需要底部弹出框的应用,不妨尝试一下这个组件,为你的应用添加更丰富的交互体验。


http://www.ppmy.cn/embedded/121140.html

相关文章

Python编码系列—Python访问者模式:为对象结构添加新功能的艺术

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

探索机器学习中的特征选择技术

在机器学习和数据科学领域&#xff0c;特征选择是一个关键步骤&#xff0c;它不仅有助于提高模型的性能&#xff0c;还能帮助我们更好地理解数据。本文将深入探讨特征选择的重要性、常见方法以及如何在实际项目中应用这些技术。 一、特征选择的重要性 降低维度&#xff1a;减…

【JavaEE】——线程池大总结

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c; 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 引入&#xff1a;问题引入 一&#xff1a;解决方案 1&#xff1a;方案一——协程/纤程 &#xff08;1…

ubuntu配置python环境

ubuntu新版一般默认安装python3&#xff0c;22版本对应的是python3.10. 问题1&#xff1a;直接python提示没有对应命令&#xff0c;必须要使用python3 方法&#xff1a;sudo apt-get install python-is-python3问题2&#xff1a;安装pip, venv 方法&#xff1a;sudo apt insta…

RBAC权限模型

在小型的管理系统中我们可以来区分管理员和用户&#xff0c;呈现不同的页面&#xff0c;但随着系统的开发&#xff0c;上述的显然不现实。包括想要实现更细粒度的权限控制。RBAC权限模型可以完美的实现权限的控制。 RBAC &#xff08;role based access control )基于角色的权…

发掘3D文件格式的无限潜力:打造沉浸式虚拟世界

在当今数字化时代&#xff0c;3D技术的应用范围日益广泛&#xff0c;涵盖电影后期制作、产品原型设计、虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;、游戏等众多领域。而3D文件格式作为3D技术的核心组成部分&#xff0c;对于实现3D数据和模型的存…

[Day 79] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

區塊鏈在遊戲產業中的應用 區塊鏈技術已經開始在遊戲產業中引發革命&#xff0c;這項技術的分散化、透明性和安全性為遊戲世界帶來了許多創新應用。從虛擬物品的擁有權到去中心化市場、NFT遊戲資產交易&#xff0c;以及遊戲內經濟系統的構建&#xff0c;區塊鏈提供了強大的工具…

TypeScript编译选项

编译单个文件 tsc file_name tsc .\src\lab.ts自动编译单个文件&#xff08;类似于debug模式&#xff09; tsc file_name -w tsc .\src\lab.ts -w编译整个项目 需要有tsconfig.json配置文件。 tsc -w tsc -wtsconfig.json配置文件 include&#xff1a;用来指定哪些ts文件…