Flutter中垂直ListWheelScrollView内嵌水平ListView滑动失效问题
问题:ListWheelScrollView子项内的水平ListView滑动无响应
- 单个子项渲染正常,但将包含水平ListView的轮播组件作为ListWheelScrollView的子项时,水平滑动操作无法被识别
- 使用普通ListView搭配ScrollController时功能正常,但需求要求滚动时自动定位到最近子项,因此必须使用
FixedExtentScrollController
使用的滚动控制器
final ScrollController scrollController = FixedExtentScrollController();
ListWheelScrollView 实现代码
Widget build(BuildContext context) { return SizedBox( height: MediaQuery.of(context).size.height, child: ListWheelScrollView.useDelegate( itemExtent: MediaQuery.of(context).size.height * 0.87, perspective: 0.001, physics: const FixedExtentScrollPhysics(), controller: scrollController, childDelegate: ListWheelChildBuilderDelegate( childCount: data.length, builder: (BuildContext context, int index) { return iStreamWidget.render(data[index]); }, ), ), ); }
子项内的水平ListView代码
滚动控制器定义
final ScrollController scrollController = FixedExtentScrollController();
ListView实现
Container( height: height * 0.88, padding: const EdgeInsets.symmetric( horizontal: 20.0, vertical: 35.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildTitle(carouselPostModel.title, postModel.postFontType, context), Expanded( child: SizedBox( width: double.infinity, child: ListView.separated( itemCount: descriptionList.length, scrollDirection: Axis.horizontal, shrinkWrap: true, controller: scrollController, physics: const BouncingScrollPhysics(), itemBuilder: (BuildContext context, int index) { return _buildCard( imageUrls[index], descriptionList[index], postModel.postFontType, context, ); }, separatorBuilder: (index, context) { return const SizedBox( width: 10.0, ); }), ) ), ], ), );
解决方案
问题根源是ListWheelScrollView的手势识别会优先拦截滑动事件,导致子项内的水平ListView无法获取事件。可通过以下方式解决:
方法1:给子项的水平ListView添加手势拦截
用GestureDetector包裹水平ListView,手动处理水平滑动事件,避免父级拦截:
// 注意:子级需改用普通ScrollController,不要和父级共用FixedExtentScrollController final ScrollController horizontalScrollController = ScrollController(); GestureDetector( onHorizontalDragUpdate: (details) { horizontalScrollController.jumpTo( horizontalScrollController.offset - details.delta.dx ); }, child: ListView.separated( controller: horizontalScrollController, physics: const NeverScrollableScrollPhysics(), // 关闭原生滚动逻辑 // 其余原有代码不变 ), )
方法2:修改ListWheelScrollView的手势识别规则
通过NotificationListener让父级在检测到水平滑动时不拦截事件:
NotificationListener<ScrollNotification>( onNotification: (notification) { // 水平滑动时,阻止父级拦截事件 if (notification is ScrollUpdateNotification && notification.direction != AxisDirection.down) { return false; } return true; }, child: ListWheelScrollView.useDelegate( // 原有代码不变 ), )
内容的提问来源于stack exchange,提问作者tensor
相关产品推荐
相关产品推荐

