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

如何在Flutter中实现类似速卖通(AliExpress)的分类页面?

Flutter 速卖通风格分类页面实现方案

这种双栏联动的分类布局不适合用单一Row组件直接实现,Row本身仅支持单次静态布局,无法处理长列表滚动、分类切换联动的需求,正确实现思路如下:

核心结构拆分

整体采用横向双栏结构,左侧为固定宽度的一级分类垂直滚动列表,右侧为弹性宽度的分类详情滚动区,通过选中的分类ID关联两侧内容。

具体实现步骤

  • 第一步:搭建基础布局骨架
    外层用Row包裹左右两个区域,左侧固定占屏幕宽度的1/4,右侧占剩余全部宽度:
    Row(
      children: [
        // 左侧一级分类栏
        SizedBox(
          width: MediaQuery.of(context).size.width * 0.25,
          child: _buildLeftCategoryList(),
        ),
        // 右侧分类详情区域
        const Expanded(child: _buildRightContent()),
      ],
    )
    
  • 第二步:实现左侧一级分类滚动列表
    用ListView.builder做可滚动的分类项,点击切换选中状态并更新右侧绑定的分类数据:
    ListView.builder(
      itemCount: firstLevelCategoryList.length,
      itemBuilder: (context, index) {
        bool isSelected = currentSelectedCategoryId == firstLevelCategoryList[index].id;
        return GestureDetector(
          onTap: () => setState(() {
            currentSelectedCategoryId = firstLevelCategoryList[index].id;
          }),
          child: Container(
            height: 48,
            alignment: Alignment.center,
            color: isSelected ? Colors.white : const Color(0xFFF7F7F7),
            child: Text(
              firstLevelCategoryList[index].name,
              style: TextStyle(
                color: isSelected ? Colors.redAccent : Colors.black87,
                fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
                fontSize: 14,
              ),
            ),
          ),
        );
      },
    )
    
  • 第三步:实现右侧分类详情区域
    右侧为多模块可滚动布局,从上到下依次为顶部Banner、二级分类标题、三级分类网格,采用SingleChildScrollView嵌套Column实现,注意处理内部网格的滚动冲突:
    SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 顶部分类Banner
          Container(
            height: 120,
            margin: const EdgeInsets.all(8),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(8),
              image: DecorationImage(
                image: NetworkImage(currentSelectedCategory.bannerUrl),
                fit: BoxFit.cover,
              ),
            ),
          ),
          // 二级分类分组列表
          ...currentSelectedCategory.subCategoryList.map((subCate) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                  child: Text(
                    subCate.name,
                    style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
                  ),
                ),
                // 三级分类网格
                GridView.builder(
                  physics: const NeverScrollableScrollPhysics(),
                  shrinkWrap: true,
                  padding: const EdgeInsets.symmetric(horizontal: 8),
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3,
                    childAspectRatio: 0.85,
                    crossAxisSpacing: 8,
                    mainAxisSpacing: 8,
                  ),
                  itemCount: subCate.thirdLevelCategoryList.length,
                  itemBuilder: (context, index) {
                    final item = subCate.thirdLevelCategoryList[index];
                    return Column(
                      children: [
                        Expanded(
                          child: Container(
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(8),
                              image: DecorationImage(
                                image: NetworkImage(item.iconUrl),
                                fit: BoxFit.cover,
                              ),
                            ),
                          ),
                        ),
                        const SizedBox(height: 4),
                        Text(
                          item.name,
                          style: const TextStyle(fontSize: 12),
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        )
                      ],
                    );
                  },
                )
              ],
            );
          }).toList()
        ],
      ),
    )
    

注意事项

如果分类数据量较大,推荐将右侧的SingleChildScrollView+GridView组合替换为CustomScrollView嵌套SliverGrid、SliverList组件,可大幅提升滚动性能;如果需要实现右侧滚动时左侧自动切换对应一级分类的效果,可通过监听右侧滚动偏移量,计算当前可视区域对应的一级分类ID同步到左侧即可。

内容的提问来源于stack exchange,提问作者Ómár Táĥá

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:18:03