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

如何使用Sliver实现可横向滚动的Flutter网格视图

在Flutter的CustomScrollView中实现横向滚动的SliverGrid

问题描述

我需要在CustomScrollView的slivers数组里实现一个横向滚动的网格视图,目前代码只能显示成纵向列表。试过用嵌套Container的方式实现横向网格,但想通过动态生成(比如list.generate)构建子项却没成功,而且我的CustomScrollView中还有其他滚动列表组件。

当前可运行但显示为纵向的代码:

body: CustomScrollView(
    slivers: [
      SliverPadding(
        padding: EdgeInsets.symmetric(horizontal: 16.0),
        sliver: SliverGrid(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            childAspectRatio: 2,
            crossAxisSpacing: 16,
            mainAxisSpacing: 16,
            crossAxisCount: 2,
          ),
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int i) {
              return InkWell(
                onTap: () {},
                child: ClipRRect(
                  clipBehavior: Clip.antiAlias,
                  borderRadius: BorderRadius.circular(8),
                  child: Container(
                    height: 200,
                    width: double.infinity,
                    decoration: BoxDecoration(
                        image: DecorationImage(
                          image:
                              CachedNetworkImageProvider('categoryImage'),
                          fit: BoxFit.cover,
                          onError: (exception, stackTrace) =>
                              LoadingImage(),
                        ),
                        gradient: const LinearGradient(
                          begin: Alignment.topLeft,
                          end: Alignment.bottomRight,
                          colors: [
                            Color(0x1FFFFFFF),
                            Color(0x463B3B3B),
                          ],
                        ),
                        borderRadius: BorderRadius.circular(8),
                        boxShadow: [
                          BoxShadow(
                              color: Colors.grey.shade900,
                              offset: const Offset(1, 1),
                              spreadRadius: 1,
                              blurRadius: 50,
                              blurStyle: BlurStyle.outer),
                        ]),
                    child: Container(
                      padding: const EdgeInsets.all(10),
                      height: 100,
                      color: Colors.transparent,
                      alignment: Alignment.bottomLeft,
                      width: double.infinity,
                      child: Text(
                        "title",
                        overflow: TextOverflow.ellipsis,
                        style: Theme.of(context).textTheme.bodyText1!,
                      ),
                    ),
                  ),
                ),
              );
            },
            childCount: count.length,
          ),
        ),
      ),
    ],
  )

解决方案

SliverGrid本身会跟随CustomScrollView的纵向滚动,要实现横向网格,需要把横向滚动的网格包装成适配sliver的组件。以下是修改后的完整代码:

body: CustomScrollView(
  slivers: [
    // 这里可以保留你原有的其他sliver组件
    SliverPadding(
      padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 16),
      sliver: SliverToBoxAdapter(
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: SizedBox(
            // 计算总宽度:屏幕宽度 × (item总数 / 列数),这里列数是2
            width: MediaQuery.of(context).size.width * (count.length / 2),
            child: GridView.builder(
              shrinkWrap: true,
              // 关闭GridView自身的滚动,避免和外层横向滚动冲突
              physics: const NeverScrollableScrollPhysics(),
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                childAspectRatio: 2,
                crossAxisSpacing: 16,
                mainAxisSpacing: 16,
                crossAxisCount: 2,
              ),
              itemCount: count.length,
              itemBuilder: (BuildContext context, int i) {
                return InkWell(
                  onTap: () {},
                  child: ClipRRect(
                    clipBehavior: Clip.antiAlias,
                    borderRadius: BorderRadius.circular(8),
                    child: Container(
                      decoration: BoxDecoration(
                        image: DecorationImage(
                          image: CachedNetworkImageProvider('categoryImage'),
                          fit: BoxFit.cover,
                          onError: (exception, stackTrace) => const LoadingImage(),
                        ),
                        gradient: const LinearGradient(
                          begin: Alignment.topLeft,
                          end: Alignment.bottomRight,
                          colors: [
                            Color(0x1FFFFFFF),
                            Color(0x463B3B3B),
                          ],
                        ),
                        borderRadius: BorderRadius.circular(8),
                        boxShadow: [
                          BoxShadow(
                            color: Colors.grey.shade900,
                            offset: const Offset(1, 1),
                            spreadRadius: 1,
                            blurRadius: 50,
                            blurStyle: BlurStyle.outer,
                          ),
                        ],
                      ),
                      child: Container(
                        padding: const EdgeInsets.all(10),
                        alignment: Alignment.bottomLeft,
                        child: Text(
                          "title",
                          overflow: TextOverflow.ellipsis,
                          style: Theme.of(context).textTheme.bodyText1!,
                        ),
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      ),
    ),
    // 这里可以添加其他sliver组件
  ],
)

关键修改说明

  • SliverToBoxAdapter:把非sliver类型的横向滚动组件转换成sliver,才能加入CustomScrollView的slivers数组
  • SingleChildScrollView:设置scrollDirection: Axis.horizontal提供横向滚动能力
  • SizedBox:给GridView设置固定宽度,确保横向滚动的范围正确,计算公式根据列数调整
  • GridView.builder:
    • shrinkWrap: true:让GridView根据内容高度自适应,避免不必要的滚动
    • physics: NeverScrollableScrollPhysics():关闭自身滚动,防止和外层横向滚动冲突
  • 动态生成子项:通过itemBuilder和itemCount实现动态渲染,和你之前的逻辑一致,也可以替换成List.generate构建子列表(比如children: List.generate(count.length, (i) => ...))

内容的提问来源于stack exchange,提问作者Digamber negi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:35:48