Flutter:如何为ListView设置滚动阈值兼容LongPressDraggable
问题解决:ListView中LongPressDraggable的微小移动导致长按失效
问题描述
在包含LongPressDraggable项的ListView中,触摸列表元素时,手指的微小移动会触发ListView的滚动,进而中断长按事件,必须抬起手指重新触摸才能触发。已将LongPressDraggable的delay设为50毫秒改善体验,但需要为ListView设置最小移动距离阈值,只有当移动超过该距离时才触发滚动,否则不响应滚动,保证长按事件正常触发。
解决方案
通过自定义ScrollBehavior,修改ListView滚动识别器的最小拖拽距离,让ListView忽略设定范围内的微小移动。具体步骤如下:
1. 自定义ScrollBehavior类
创建继承自MaterialScrollBehavior的类,重写拖拽识别器初始化逻辑,设置最小移动距离:
class CustomScrollBehavior extends MaterialScrollBehavior { final double minDragDistance; CustomScrollBehavior({this.minDragDistance = 10.0}); @override Set<PointerDeviceKind> get dragDevices => { PointerDeviceKind.touch, PointerDeviceKind.mouse, }; @override DragGestureRecognizerFactory<VerticalDragGestureRecognizer> get verticalDragGestureRecognizerFactory => _createDragRecognizerFactory((kind) => VerticalDragGestureRecognizer(kind: kind)); @override DragGestureRecognizerFactory<HorizontalDragGestureRecognizer> get horizontalDragGestureRecognizerFactory => _createDragRecognizerFactory((kind) => HorizontalDragGestureRecognizer(kind: kind)); DragGestureRecognizerFactory<T> _createDragRecognizerFactory<T extends DragGestureRecognizer>( T Function(PointerDeviceKind) constructor) { return DragGestureRecognizerFactory( constructor, (instance) => instance..minDistance = minDragDistance, ); } }
2. 用ScrollConfiguration包裹ListView
将原ListView用ScrollConfiguration包裹,传入自定义的CustomScrollBehavior,设置需要的最小移动距离(示例中设为15像素):
SizedBox( width: 100, height: 200, child: ScrollConfiguration( behavior: CustomScrollBehavior(minDragDistance: 15.0), child: ListView.builder( itemCount: list.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: LongPressDraggable<Widget>( delay: const Duration(milliseconds: 50), // 原代码此处缺少逗号,需补上 data: list[index], feedback: AnimatedScale( duration: const Duration(seconds: 1), scale: 1.25, child: list[index], ), childWhenDragging: Opacity(opacity: 0.5, child: list[index]), child: list[index], ), ); }, ), ), )
额外注意
原代码中LongPressDraggable的delay参数后缺少逗号,会导致编译错误,需补上。
原理说明
自定义的ScrollBehavior会覆盖ListView默认的拖拽识别器,设置minDistance后,只有当手指移动距离超过该值时,滚动识别器才会触发滚动逻辑,在此之前的微小移动不会中断长按事件,从而保证LongPressDraggable的长按触发不受干扰。
内容的提问来源于stack exchange,提问作者Jaime Roman
相关产品推荐
相关产品推荐

