Flutter如何实现不同滚动视图下多个SliverAppBar依次固定吸顶
问题根因
NestedScrollView的内外滚动视图的Sliver吸顶逻辑相互独立,内部CustomScrollView中标记为pinned的SliverAppBar默认以自身滚动容器的顶部作为吸顶基准,而NestedScrollView的内部滚动容器顶部与外部SliverAppBar(含TabBar)的底部重合,因此内部AppBar吸顶时会偏移到外部AppBar下方被遮挡。
可行解决方案
使用Flutter官方原生配套组件即可解决,无需引入第三方依赖,核心是通过SliverOverlapAbsorber和SliverOverlapInjector组合,让内部滚动视图自动感知外部头部高度,调整吸顶基准位置。
修改后的完整代码
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: const Test(), ); } } class Test extends StatelessWidget { const Test({super.key}); @override Widget build(BuildContext context) { final List<String> tabs = ['Tab 1', 'Tab 2']; return DefaultTabController( length: tabs.length, child: Scaffold( body: NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ // 外部SliverAppBar包裹SliverOverlapAbsorber,采集外部头部高度 SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( title: const Text('1st App Bar'), pinned: true, forceElevated: innerBoxIsScrolled, bottom: TabBar( tabs: tabs.map((String name) => Tab(text: name)).toList(), ), ), ), ]; }, body: TabBarView( children: [ CustomScrollView( slivers: [ // 内部滚动视图开头注入外部头部高度,自动偏移内容与吸顶基准 SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), SliverPadding( padding: const EdgeInsets.all(8.0), sliver: SliverFixedExtentList( itemExtent: 48.0, delegate: SliverChildBuilderDelegate( (context, index) { return ListTile( title: Text('Item $index'), ); }, childCount: 3, ), ), ), const SliverAppBar( toolbarHeight: 150, pinned: true, backgroundColor: Colors.purple, title: Text('2nd App Bar'), ), SliverPadding( padding: const EdgeInsets.all(8.0), sliver: SliverFixedExtentList( itemExtent: 48.0, delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile( title: Text('Item $index'), ); }, childCount: 20, ), ), ), ], ), const Placeholder(), ], ), ), ), ); } }
方案说明
SliverOverlapAbsorber会自动计算外部固定头部的总高度(包含SliverAppBar和底部TabBar的实际高度),通过handle同步给内部滚动视图SliverOverlapInjector会在内部滚动视图顶部插入对应高度的空白区域,同时内部pinned属性的Sliver组件会自动将吸顶基准向下偏移对应高度,刚好固定在外部TabBar的下方,不会被遮挡- 该方案无需硬编码固定高度,适配不同设备的状态栏、AppBar高度,也不会影响第二个Tab的正常布局
内容的提问来源于stack exchange,提问作者Enqvida
相关产品推荐
相关产品推荐

