如何在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áĥá
相关产品推荐
相关产品推荐

