ScrollablePositionedList嵌套水平ListView触发断言错误咨询
问题分析与解决办法
错误到底是什么意思?
这个断言是scrollable_positioned_list库内部的校验逻辑触发的:
- 外层的
ScrollablePositionedList默认是垂直滚动的,它内部会监听滚动通知,并且只认垂直方向的滚动事件 - 当你滑动内部的水平ListView到两端时,水平ListView会发出水平方向的滚动通知(比如滚动到底/顶的结束通知),外层的垂直滚动列表收到这个不匹配轴方向的通知后,就触发了
notification.metrics.axis == widget.axis的断言失败。
现在UI正常,以后会出问题吗?
目前看起来功能没问题,但有几个潜在隐患:
- Debug模式下每次触发都会弹出错误,打断开发流程;虽然Release模式断言会被移除,但如果库后续版本调整了处理逻辑,说不定Release也会出异常
- 频繁的断言日志会淹没其他有用的调试信息,给排查其他问题添乱
- 后续如果依赖库更新,这种跨轴的滚动通知可能引发更严重的滚动冲突或状态异常
怎么修复?
给内部的水平ListView套一层NotificationListener,把水平方向的滚动通知拦下来,不让它传到外层的垂直列表里:
修改后的代码如下:
import 'package:flutter/material.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const ScrollDemo(), ); } } class ScrollDemo extends StatelessWidget { const ScrollDemo({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return ScrollablePositionedList.builder( shrinkWrap: true, itemCount: 10, itemBuilder: (context, index) => index == 1 ? SizedBox( height: 100, child: NotificationListener<ScrollNotification>( // 拦截水平滚动通知,不向上传递 onNotification: (notification) { return notification.metrics.axis == Axis.horizontal; }, child: ListView.builder( itemCount: 5, scrollDirection: Axis.horizontal, shrinkWrap: true, itemBuilder: (context, index) => Container( margin: const EdgeInsets.all(5), height: 100, width: 200, color: Colors.red, ), ), ), ) : Container( height: 100, width: 200, color: Colors.green, ), ); } }
修复逻辑
NotificationListener会接住子Widget发出的滚动通知,返回true就表示这个通知已经被处理了,不会再往上传给外层的ScrollablePositionedList,这样外层就不会收到轴方向不匹配的通知,断言自然就不会触发了。
内容的提问来源于stack exchange,提问作者im_jm
相关产品推荐
相关产品推荐

