Dart/Flutter中ListView分组展示子数据异常的解决方案
方案1:最小改动现有代码(无需调整数据结构)
你当前重复展示分组名的原因是每个列表项都固定渲染了分组标题,只需要加条件判断,仅在分组第一次出现时展示标题即可,修改后的代码如下:
// 首先确保你的原始列表已经按照分组字段排序,同组元素连续排列 _mOfferList.sort((a, b) => (a.offerBaseProductBrandTitle ?? "").compareTo(b.offerBaseProductBrandTitle ?? "")); ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: _mOfferList == null ? 0 : _mOfferList.length, itemBuilder: (BuildContext context, index) { // 判断当前项是否需要展示分组标题 bool showGroupTitle = index == 0 ? true : _mOfferList[index].offerBaseProductBrandTitle != _mOfferList[index-1].offerBaseProductBrandTitle; return Card( elevation: 1, child: Column( children: [ // 仅符合条件时渲染分组标题 if (showGroupTitle) Align( alignment: Alignment.centerLeft, child: Padding( padding: const EdgeInsets.all(8.0), child: Text( _mOfferList[index].offerBaseProductBrandTitle, style: TextStyle(fontSize: 13.0), ), ), ), // 子项加左侧缩进实现你要的排版效果 Padding( padding: const EdgeInsets.only(left: 24.0, right: 8.0, bottom: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( flex: 1, child: Container( padding: EdgeInsets.all(10.0), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( flex: 1, child: _mOfferList[index].offerTitle == null ? Text(" ", style: TextStyle(fontSize: 13.0)) : Text( _mOfferList[index].offerTitle, textAlign: TextAlign.left, style: TextStyle(fontSize: 13.0), ), ) ], ) ], ), ), ), ], ), ), ], ) ); } )
方案2:预处理数据为分组结构(可扩展性更高)
如果后续需要实现分组折叠、统计分组数量等功能,更推荐先把原始数据转成分组Map再渲染,实现代码如下:
- 先对原始数据做分组处理
// 新增分组数据处理逻辑 Map<String, List<PromotionOfferModel>> get groupedOffers { if (_mOfferList == null || _mOfferList.isEmpty) return {}; final Map<String, List<PromotionOfferModel>> result = {}; for (final item in _mOfferList) { final groupKey = item.offerBaseProductBrandTitle ?? "未分组"; if (!result.containsKey(groupKey)) { result[groupKey] = []; } result[groupKey]!.add(item); } return result; }
- 渲染分组列表
ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: groupedOffers.length, itemBuilder: (context, groupIndex) { final groupName = groupedOffers.keys.elementAt(groupIndex); final groupItems = groupedOffers[groupName]!; return Card( elevation: 1, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 分组标题 Padding( padding: const EdgeInsets.all(8.0), child: Text( groupName, style: TextStyle(fontSize: 13.0), ), ), // 分组下所有子项 ...groupItems.map((item) => Padding( padding: const EdgeInsets.only(left: 24.0, right: 8.0, bottom: 8.0), child: Row( children: [ Expanded( child: Text( item.offerTitle ?? "", style: TextStyle(fontSize: 13.0), ), ) ], ), )).toList() ], ), ); } )
内容的提问来源于stack exchange,提问作者Flutter Box
相关产品推荐
相关产品推荐

