Flutter中CustomScrollView滚动时SliverList穿透SliverAppBar问题
问题描述
我在带有顶部区域的页面内使用CustomScrollView,其中包含固定的SliverAppBar(未停靠在屏幕顶部)。滚动时,SliverList的内容会短暂以1像素线条形式显示在SliverAppBar上方;尝试过SliverPersistentHeader、SliverOverlapAbsorber搭配NestedScrollView仍未解决,且该问题也出现在SliverAppBar标题与底部之间。
相关代码
return Scaffold( appBar: CharacterListAppBar(), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey.shade300, ), child: SearchBar(), ), // Search bar Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Filters(), ), Expanded( child: FutureBuilder<Response>( future: _characterList, builder: (context, snapshot) { if (snapshot.hasData) { return CustomScrollView( physics: const BouncingScrollPhysics(), slivers: [ const SliverAppBar( automaticallyImplyLeading: false, toolbarHeight: 8, backgroundColor: AppColors.backgroundColor, pinned: true, primary: true, ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) => Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 24), child: CharacterSlidingCard( character: const { "name": "Gimli", "race": "Nain", "profile": "Warrior", "level": 1, }, index: 0, selected: _selectedIndex == 0, onTap: () => _onSelectCard(0), ), ), childCount: 18, ), ), ], ); } return const Center( child: CircularProgressIndicator(), ); }, ), ), // Character list ], ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.of(context).pushNamed(CharacterCreationPage.routeName); }, backgroundColor: AppColors.backgroundColorDark, child: const Icon(Icons.add_outlined, size: 40), ), );
问题截图

解决方案
这个问题属于Sliver组件滚动时的像素渲染偏移问题,可通过以下几种方式解决:
给SliverAppBar添加遮罩层:给
SliverAppBar添加同背景色的顶部边框或阴影,覆盖溢出的1像素内容。示例:const SliverAppBar( automaticallyImplyLeading: false, toolbarHeight: 8, backgroundColor: AppColors.backgroundColor, pinned: true, primary: true, elevation: 1, shadowColor: AppColors.backgroundColor, // 阴影色与背景一致 )或添加顶部边框:
const SliverAppBar( // 原有属性不变 bottom: PreferredSize( preferredSize: Size.fromHeight(0), child: Container( height: 1, color: AppColors.backgroundColor, ), ), )强制裁剪CustomScrollView内容:将
CustomScrollView的clipBehavior设置为Clip.hardEdge,限制内容不超出边界:return CustomScrollView( physics: const BouncingScrollPhysics(), clipBehavior: Clip.hardEdge, // 添加该行 slivers: [ // 现有sliver组件 ], );替换SliverAppBar为SliverToBoxAdapter:若仅需固定高度色块,用
SliverToBoxAdapter替代SliverAppBar,规避其内部渲染逻辑导致的偏移:SliverToBoxAdapter( child: Container( height: 8, color: AppColors.backgroundColor, ), ),
内容的提问来源于stack exchange,提问作者Remi Martin
相关产品推荐
相关产品推荐

