Flutter分组GridView实现优化求助:高效展示多分组列表项
分组网格列表的低代码实现方案
核心思路是用单个多组件容器+多类型Item替代多个GridView,既减少冗余代码,又方便后续维护。以下是Android和Flutter两个主流平台的实现方案:
Android 端实现
1. 定义分组数据结构
data class GroupItem( val groupTitle: String, // 分组标题(如"汽车组") val items: List<String> // 分组下的子项集合 )
2. 自定义RecyclerView适配器
通过区分Item类型,同时处理分组标题和网格子项:
class GroupGridAdapter(private val dataList: List<GroupItem>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { companion object { private const val TYPE_GROUP_TITLE = 0 private const val TYPE_GROUP_ITEM = 1 } override fun getItemViewType(position: Int): Int { var currentPos = 0 for (group in dataList) { if (currentPos == position) return TYPE_GROUP_TITLE currentPos++ if (position < currentPos + group.items.size) return TYPE_GROUP_ITEM currentPos += group.items.size } return TYPE_GROUP_ITEM } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return if (viewType == TYPE_GROUP_TITLE) { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_group_title, parent, false) TitleViewHolder(view) } else { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_grid_child, parent, false) ItemViewHolder(view) } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { var currentPos = 0 for (group in dataList) { if (currentPos == position) { (holder as TitleViewHolder).tvTitle.text = group.groupTitle return } currentPos++ if (position < currentPos + group.items.size) { val itemIndex = position - currentPos (holder as ItemViewHolder).tvItem.text = group.items[itemIndex] return } currentPos += group.items.size } } override fun getItemCount(): Int { return dataList.sumOf { 1 + it.items.size } // 每个组=1个标题位+子项数量 } class TitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvTitle: TextView = itemView.findViewById(R.id.tv_group_title) } class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvItem: TextView = itemView.findViewById(R.id.tv_grid_item) } }
3. 配置布局管理器
让分组标题占满整行,子项按网格排列:
val gridLayoutManager = GridLayoutManager(context, 3) // 设置每行3个网格 gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { override fun getSpanSize(position: Int): Int { return if (adapter.getItemViewType(position) == GroupGridAdapter.TYPE_GROUP_TITLE) 3 else 1 } } recyclerView.layoutManager = gridLayoutManager recyclerView.adapter = GroupGridAdapter(groupDataList)
Flutter 端实现
1. 定义分组数据类
class GroupItem { final String groupTitle; final List<String> items; GroupItem({required this.groupTitle, required this.items}); }
2. 简洁嵌套实现(低代码首选)
用ListView嵌套GridView,自动实现分组滚动:
ListView.builder( itemCount: groupDataList.length, itemBuilder: (context, index) { final group = groupDataList[index]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 分组标题 Padding( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Text( group.groupTitle, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ), // 分组子项网格 GridView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 8, mainAxisSpacing: 8, ), itemCount: group.items.length, itemBuilder: (context, itemIndex) { return Container( alignment: Alignment.center, color: Colors.grey[200], child: Text(group.items[itemIndex]), ); }, ), ], ); }, )
实现效果:每个分组标题占整行,下方是对应组的网格子项,整体可纵向滚动,和你描述的示例动效完全匹配。
内容的提问来源于stack exchange,提问作者Abu Bakar
相关产品推荐
相关产品推荐

