You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter GridView滚动时上方过滤按钮无法跟随AppBar上滑问题求助

问题修复方案

问题原因

你当前将过滤按钮组件放在了NestedScrollView的body属性中,只有headerSliverBuilder回调中返回的Sliver系列组件才会跟随页面滚动同步收起,body区域默认固定在头部下方,因此出现过滤按钮无法滑动的问题。

修复步骤

  1. 将过滤按钮、_avatarBar组件转移到headerSliverBuilder中,用SliverToBoxAdapter包裹作为可折叠头部的一部分
  2. 给SliverAppBar补充滑动收起的必要配置
  3. 调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:57:04