Scaffold嵌套NestedScrollView时点击SliverAppbar下内容自动滚顶问题
问题根因
代码中手动将NestedScrollView的主滚动控制器绑定给了内部的ListView,破坏了NestedScrollView原生的嵌套滚动协调逻辑:点击列表项时触发了滚动位置矫正规则,就会出现自动滚动到顶部的异常。同时如果要在Tab内部使用带悬浮按钮的Scaffold,需要额外配置避免Scaffold占用主滚动控制器。
修复方案
- 删掉内部ListView的
controller: scrollController配置,NestedScrollView默认会自动处理内外层滚动的协调逻辑,不需要手动绑定控制器 - 给Tab页内部的Scaffold添加
primary: false配置,避免Scaffold默认抢占主滚动控制器导致嵌套滚动异常
修复后可运行代码
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { static const String _title = 'Flutter Code Sample'; @override Widget build(BuildContext context) { return MaterialApp( title: _title, home: MyStatelessWidget(), ); } } class MyStatelessWidget extends StatelessWidget { MyStatelessWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return DefaultTabController( length: 3, child: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) { return [ SliverAppBar( floating: true, pinned: true, bottom: const TabBar( tabs: [ Tab(text: "Tab1"), Tab(text: "Tab2"), Tab(text: "Tab3"), ], ), title: const Text( 'Appbar', style: TextStyle(color: Colors.black), ), expandedHeight: 180, ), ]; }, body: TabBarView( children: [ // 每个Tab页都是独立的带悬浮按钮的Scaffold _buildTabPage(0), _buildTabPage(1), _buildTabPage(2), ], ), ), ); } Widget _buildTabPage(int tabIndex) { return Scaffold( // 关键配置:禁止当前Scaffold抢占主滚动控制器 primary: false, floatingActionButton: FloatingActionButton( onPressed: () {}, child: const Icon(Icons.add), ), body: ListView.separated( padding: EdgeInsets.zero, itemBuilder: (context, index) { return Container( height: 100, width: double.infinity, alignment: Alignment.centerLeft, child: Text('Tab $tabIndex Index: $index'), ); }, itemCount: 1000, separatorBuilder: (BuildContext context, int index) { return const Divider(); }, ), ); } }
补充说明
如果需要主动控制内部列表的滚动位置,可以给每个子页的ListView单独创建独立的ScrollController,不要复用NestedScrollView的主控制器即可。
内容的提问来源于stack exchange,提问作者Khoa Le
相关产品推荐
相关产品推荐

