哈喽,我是老刘
几年前分享了一篇GestureDetector嵌套ListView的文章
Flutter多控件滑动事件联动(滑动冲突处理) - 知乎 (zhihu.com)
由于文章中只给出了关键部位的代码,另外使用的技术也偏底层
所以很多同学私信我要完整的源码
这里把原先的方案整理一下,另外也给出完整的代码供大家参考
我们先一点一点来看这个问题
滑动关闭组件
首先大家一定在各种App中见过这个滑动关闭组件
就是手指向下滑动,组件跟随手指移动
手指抬起后组件滑出屏幕
我们先来实现这个组件,然后来讨论一下如果组件中的内容时一个ListView,要怎么处理
如果这个组件的内容时固定内容,不是ListView这样的可滚动组件
实现起来其实很简单
我这里直接放源码
import 'package:flutter/material.dart';
class CloseOnSwipeDownWidget extends StatefulWidget {
final Widget child;
const CloseOnSwipeDownWidget({
Key? key,
required this.child,
}) : super(key: key);
@override
CloseOnSwipeDownWidgetState createState() => CloseOnSwipeDownWidgetState();
}
class CloseOnSwipeDownWidgetState extends State
with TickerProviderStateMixin {
double yOffset = 0.0;
double initialPosition = 0.0;
bool isAnimatingOut = false;
int animTime = 0;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onVerticalDragDown: (details) {
initialPosition = details.globalPosition.dy;
},
onVerticalDragUpdate: (details) {
double updatedPosition = details.globalPosition.dy;
double deltaY = updatedPosition - initialPosition;
animTime = 0;
setState(() {
yOffset = yOffset + deltaY;
initialPosition = updatedPosition;
});
},
onVerticalDragEnd: (details) {
animTime = 300;
if (yOffset > 200) {
// 触发滑出动画
_startSlideOutAnimation();
} else {
// 触发返回原始位置的动画
_startReturnToOriginalPositionAnimation();
}
},
child: Stack(
children: [
AnimatedPositioned( // 组件跟随手指位移,以及抬起手指后组件移动动画
duration: Duration(milliseconds: animTime),
curve: Curves.easeInOut,
top: yOffset,
left: 0,
right: 0,
child: widget.child,
onEnd: () {