Flutter中如何保留BottomNavigation切换时ListView的滚动位置
解决方案
当前代码中,每次切换底部导航项时,setState会触发页面重建,而TodoList和TodoCompletedList是无状态组件(StatelessWidget),重建时会重新创建ListView,导致滚动位置丢失。只需将列表组件改为有状态组件并混入AutomaticKeepAliveClientMixin,就能保留滚动状态。
修改后的代码
待办事项列表组件
class TodoList extends StatefulWidget { @override State<TodoList> createState() => _TodoListState(); } class _TodoListState extends State<TodoList> with AutomaticKeepAliveClientMixin { // 告知Flutter需要保留该组件状态 @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { // 必须调用super.build,否则KeepAlive不生效 super.build(context); return ListView.builder( itemCount: 40, itemBuilder: (context, index) { return ListTile( leading: CircleAvatar(), title: Text('Item No.' + (index + 1).toString()), ); }); } }
已完成事项列表组件
class TodoCompletedList extends StatefulWidget { @override State<TodoCompletedList> createState() => _TodoCompletedListState(); } class _TodoCompletedListState extends State<TodoCompletedList> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { super.build(context); return ListView.builder( itemCount: 10, itemBuilder: (context, index) { return ListTile( leading: CircleAvatar(), title: Text('Item No.' + (index + 1).toString()), ); }); } }
HomePage代码无需修改,保持原逻辑即可。
需学习的相关技术点
- AutomaticKeepAliveClientMixin:用于在页面切换时保留Widget的状态,避免重建时丢失滚动位置、输入内容等状态。核心是重写
wantKeepAlive返回true,并在build方法中调用super.build(context)。 - StatefulWidget与StatelessWidget的区别:StatelessWidget无状态,每次重建都会重新实例化;StatefulWidget的State对象可以被保留(结合KeepAlive),从而维持组件的状态信息。
- Flutter的Widget重建机制:调用
setState会触发当前State的build方法,子Widget若为Stateless则会被重新创建,而Stateful的State若被标记为KeepAlive则不会被销毁。
内容的提问来源于stack exchange,提问作者Irfan Ganatra
相关产品推荐
相关产品推荐

