卧龙区2015网站建设口碑,自驾游网站建设,网站如何做电脑和手机app,郑州比较厉害的短视频公司一、先来看下实现的效果 实现上面的效果需要解决俩个问题 当列表进行向下滑动到顶部的时候#xff0c;继续滑动可以让弹窗向下收起来弹出上下拖动的时候#xff0c;视图内容跟着上下移动、缩放大小
二、实现弹窗上下滑动的时候#xff0c;动态改变内容区的位置和大小
通过…一、先来看下实现的效果 实现上面的效果需要解决俩个问题 当列表进行向下滑动到顶部的时候继续滑动可以让弹窗向下收起来弹出上下拖动的时候视图内容跟着上下移动、缩放大小
二、实现弹窗上下滑动的时候动态改变内容区的位置和大小
通过showModalBottomSheet显示底部对话框
showModalBottomSheet(context: context,isScrollControlled: true,backgroundColor: Colors.white,transitionAnimationController: _controller,builder: (_) {///省略部分代码...},
);1、那问题来了怎么去监听对话框当前显示的高度呢 可以发现showModalBottomSheet有一个transitionAnimationController参数这个就是对话框显示的动画控制器了值为[0,1]当全部显示是为1。 那么当将弹窗设为固定高度时就可以通过这个值进行计算了 假设我们顶部留的最小空间为宽度 屏幕宽度高度 屏幕宽度 / (16 / 9)那么对话框的高度就等与 屏幕高度 - 顶部高度
///屏幕宽度
double get screenWidth MediaQuery.of(context).size.width;
///屏幕高度
double get screenHeight MediaQuery.of(context).size.height;
///顶部留的高度
double get topSpaceHeight screenWidth / (16 / 9);
///对话框高度
double get bottomSheetHeight screenHeight - topSpaceHeight;2、监听对话框高度改变
override
void initState() {super.initState();_controller BottomSheet.createAnimationController(this);_controller.addListener(() {final value _controller.value * bottomSheetHeight;///更新UI_bottomSheetController.sink.add(value);});
}override
Widget build(BuildContext context) {final bottom MediaQuery.of(context).padding.bottom;return ColoredBox(color: Colors.black,child: Stack(children: [StreamBuilderdouble(stream: _bottomSheetController.stream,initialData: 0,builder: (_, snapshot) {return Container(height: screenHeight - snapshot.data!,alignment: Alignment.center,child: Image.network(https://5b0988e595225.cdn.sohucs.com/images/20200112/75b4a498fdaa48c7813419c2d4bac477.jpeg,),);},),],),);
}通过上面这样处理内容区的上移和缩小就已经实现了 三、弹窗内容向下滑动当滑动到顶继续向下滑动时可以让对话框继续向下滑动不打断此次触摸事件
这里借鉴了这位博主的解决方案可以先看一下https://www.jianshu.com/p/4f2d10750f5c
1、在向下滑动到顶继续向下的时候动态改变弹窗内部的高度来达到弹窗下拉的效果这里本来是想通过改变transitionAnimationController.value的值来改变弹窗的高度但是实际中发现或的效果不理想不知道为什么
override
Widget build(BuildContext context) {return StreamBuilderdouble(stream: _dragController.stream,initialData: widget.height,builder: (context, snapshot) {return AnimatedContainer(height: snapshot.data ?? widget.height,duration: const Duration(milliseconds: 50),child: Column(children: [widget.pinedHeader ?? const SizedBox.shrink(),Expanded(child: Listener(onPointerMove: (event) {///没有滚动到顶部不处理if (_scrollController.offset ! 0) {return;}///获取滑动到顶部开始下拉的位置_startY ?? event.position.dy;final distance event.position.dy - _startY!;///弹窗滑动后剩余高度if ((widget.height - distance) widget.height) {return;}_dragController.sink.add(widget.height - distance);///剩余弹出高度所占百分比final percent 1 - distance / widget.height;///为了处理图片大小缩放需要使用widget.transitionAnimationController.value percent;},/// 触摸事件结束 恢复可滚动onPointerUp: (event) {_startY null;if (snapshot.data! widget.height * 0.5) {///下拉到了一半直接关闭widget.transitionAnimationController.animateTo(0,duration: const Duration(microseconds: 250));} else {///未到一半 恢复展示_dragController.sink.add(widget.height);widget.transitionAnimationController.animateTo(1,duration: const Duration(microseconds: 250));}},child: SingleChildScrollView(controller: _scrollController,physics: snapshot.data widget.height? const ClampingScrollPhysics(): const NeverScrollableScrollPhysics(),child: widget.child,),),),],),);},);
}2、解决原理
使用Listener包裹底部可滚动组件然后监听用户的滑动当滑动到了最顶部且继续向下滑动就将SingleChildScrollView的physics设置为不可滚动同时改变内容的高度同时也要改变transitionAnimationController.value的值这样内容区才会跟着移动缩放最后在触摸结束的时候进行判断是需要收起弹窗还是关闭弹窗