Flutter GridView滚动时上方过滤按钮无法跟随AppBar上滑问题求助
问题修复方案
问题原因
你当前将过滤按钮组件放在了NestedScrollView的body属性中,只有headerSliverBuilder回调中返回的Sliver系列组件才会跟随页面滚动同步收起,body区域默认固定在头部下方,因此出现过滤按钮无法滑动的问题。
修复步骤
- 将过滤按钮、_avatarBar组件转移到
headerSliverBuilder中,用SliverToBoxAdapter包裹作为可折叠头部的一部分 - 给SliverAppBar补充滑动收起的必要配置
- 调整GridView的滚动配置,和NestedScrollView实现滚动联动
修改后完整代码
build方法
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( minimum: EdgeInsets.symmetric(horizontal: 15), child: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ SliverAppBar( floating: true, // 上滑时收起,下滑时立即显示 snap: true, // 滑动停止时自动完全展开/收起 leadingWidth: 130, leading: Padding( padding: EdgeInsets.only(top: 10, bottom: 10, left: 15), child: ToggleButtons( children: <Widget>[ Text('남성', style: TextStyle(color: Colors.grey)), Text('여성', style: TextStyle(color: Colors.grey)) ], onPressed: (int index) { setState(() { for (int buttonIndex = 0; buttonIndex < _isGenderSelected.length; buttonIndex++) { _isGenderSelected[buttonIndex] = buttonIndex == index; } }); }, isSelected: _isGenderSelected, fillColor: Color.fromRGBO(43, 68, 112, 1), borderRadius: BorderRadius.circular(10), ) ), centerTitle: true, title: Text( '아바타 탐색', style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold ) ), backgroundColor: Color.fromRGBO(242, 244, 246, 1), actions: [ IconButton( icon: Icon(Icons.refresh, color: Colors.black), onPressed: () {}, ) ] ), // 新增:将过滤按钮和_avatarBar放到头部折叠区域 SliverToBoxAdapter( child: Column( children: [ _filterAvatar(), _avatarBar(), ], ), ) ], // body仅保留GridView组件 body: _avatarImages() ), ), ); }
_avatarImages方法修改
Widget _avatarImages() { return GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), // 移除shrinkWrap和禁用滚动的配置,让GridView和NestedScrollView联动滚动 padding: EdgeInsets.only(top: 10), children: [ Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[0]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[1]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[2]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[3]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[4]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[5]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[6]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[7]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[8]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[9]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[10]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[11]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[12]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[13]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[14]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[15]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[16]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[17]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[18]) ), Padding( padding: EdgeInsets.all(3), child: Image.asset(_avatarList[19]) ), ], ); }
可选配置
如果希望AppBar滑到顶部后才完全显示,不需要下滑立即弹出,可以把SliverAppBar的snap: true去掉,仅保留floating: true即可;如果需要AppBar始终在顶部显示不收起,添加pinned: true属性。
内容的提问来源于stack exchange,提问作者gs97ahn
相关产品推荐
相关产品推荐

