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

如何使用ListView.builder实现从API获取的嵌套商品列表?

使用ListView.builder展示嵌套菜品列表

1. 数据处理

先把API返回的JSON转换为Dart可处理的结构,推荐用模型类保证类型安全:

定义Product模型类

class Product {
  final String productName;

  Product({required this.productName});

  // 从JSON解析为Product对象
  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(
      productName: json["productName"].trim(), // 去除名称首尾冗余空格
    );
  }
}

解析API返回的嵌套列表

// 假设API返回的原始JSON数据
final rawData = [
  [{"productName": "Chicken Biryani Half"}, {"productName": " Chicken Momos"}],
  [{"productName": "Chicken Biryani Half"}, {"productName": "Chicken Biryani Half"}, {"productName": " Chicken Momos"}]
];

// 转换为强类型嵌套列表
final List<List<Product>> groupedProducts = rawData
    .map((group) => group.map((item) => Product.fromJson(item)).toList())
    .toList();

2. 用嵌套ListView.builder构建UI

通过两层ListView.builder实现嵌套展示:外层处理分组,内层处理每组内的菜品:

ListView.builder(
  // 外层列表条目数等于分组数量
  itemCount: groupedProducts.length,
  itemBuilder: (context, groupIndex) {
    final currentGroup = groupedProducts[groupIndex];
    
    return Card(
      margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 分组标题(可选,用于区分不同餐组/订单)
            Text(
              "餐组 ${groupIndex + 1}",
              style: const TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.w600,
              ),
            ),
            const SizedBox(height: 12),
            // 内层ListView展示当前分组的菜品
            ListView.builder(
              // 关键:让内层ListView仅占用所需空间
              shrinkWrap: true,
              // 禁用内层滚动,避免与外层滚动冲突
              physics: const NeverScrollableScrollPhysics(),
              itemCount: currentGroup.length,
              itemBuilder: (context, productIndex) {
                final product = currentGroup[productIndex];
                return ListTile(
                  leading: const Icon(Icons.fastfood),
                  title: Text(product.productName),
                );
              },
            ),
          ],
        ),
      ),
    );
  },
)

关键注意点

  • shrinkWrap: true:必须给内层ListView设置该属性,否则它会试图占用无限高度,引发布局错误。
  • NeverScrollableScrollPhysics():禁用内层ListView的滚动能力,避免和外层ListView的滚动行为冲突。
  • 类型安全:用模型类替代直接操作Map,可避免运行时类型错误,同时提升代码可维护性。

内容的提问来源于stack exchange,提问作者Prasenjit Das

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:41:24