Flutter稳定版Web端嵌套滚动双滚动条常显异常问题
问题原因
Flutter 2.5.0版本重构了滚动通知冒泡逻辑,嵌套滚动场景下,子垂直滚动组件的滚动通知会向上冒泡到父水平滚动组件的Scrollbar监听逻辑中。原有代码里仅通过depth == 0判断无法过滤掉方向不匹配的滚动通知,水平Scrollbar接收到垂直方向的滚动通知后会判定为非自身滚动事件,触发隐藏逻辑,导致异常。
可行解决方案
修改水平滚动组件外层Scrollbar的notificationPredicate判断规则,在深度判断的基础上增加滚动方向校验,仅响应水平方向的滚动通知即可解决该问题,修改后的核心代码如下:
Widget _buildHorizontalScroll() { return Scrollbar( // 若使用Flutter 3.0+版本,isAlwaysShown请替换为thumbVisibility isAlwaysShown: true, controller: _horizontalController, notificationPredicate: (notification) { // 仅处理深度为0、且为水平方向的滚动通知 return notification.depth == 0 && notification.metrics.axis == Axis.horizontal; }, // 原有子组件逻辑保持不变 child: ListView.separated( controller: _horizontalController, scrollDirection: Axis.horizontal, itemBuilder: (context, index) => Container( margin: const EdgeInsets.all(30), width: 300, color: Colors.black12, child: Column( children: [ Expanded( child: _buildVerticalScroll(index), ) ], ), ), separatorBuilder: (context, index) => const Divider( height: 30, ), itemCount: 6), ); }
如果修改后仍有异常,可在垂直滚动的ListView外层加NotificationListener,手动阻止垂直滚动通知向上冒泡,代码如下:
Widget _buildVerticalScroll(int index) { return NotificationListener<ScrollNotification>( onNotification: (notification) => true, child: Scrollbar( scrollbarOrientation: ScrollbarOrientation.right, // 若使用Flutter 3.0+版本,isAlwaysShown请替换为thumbVisibility isAlwaysShown: true, controller: _verticalController[index], child: ListView.separated( controller: _verticalController[index], itemBuilder: (context, index) => Container( margin: const EdgeInsets.all(30), height: 100, color: Colors.green, ), separatorBuilder: (context, index) => const Divider( height: 30, ), itemCount: 200), ), ); }
修改后滚动垂直列表时水平滚动条会保持常显,两个滚动条互不干扰,符合预期效果。
适配说明
- Flutter 3.0及以上版本中,
Scrollbar的isAlwaysShown属性已被标记为废弃,替换为thumbVisibility属性即可,功能完全一致。 - 该方案不影响原有滚动逻辑,滚动性能也不会受到额外影响。
内容的提问来源于stack exchange,提问作者Sulav Bimali
相关产品推荐
相关产品推荐

