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

Flutter Expandable ListView按forDuration分组实现求助

按forDuration分组实现可展开支付列表的问题修复

问题描述

我有一组支付数据,想按forDuration(月份)字段构建可展开列表,每个分组下展示对应周期内用户的姓名、邮箱及金额,但当前的ListView.builder代码无法正确显示ExpansionTile,求帮忙解决。

数据示例

{
   "status":"Success",
   "payments":[
      {
         "id":291,
         "user":{
            "id":12,
            "userID":"cvWLyHRla",
            "name":"Bill Obama",
            "email":"email@user1",
            "username":"username1",
            "profilePic":null,
            "created_at":"2023-05-08T00:52:11.000000Z"
         },
         "userID":12,
         "groupID":28,
         "paymentDueDate":"2023-11-01",
         "paymentDate":null,
         "amount":1000,
         "forDuration":"November",
         "proofOfPayment":null,
         "paymentMode":null,
         "paymentID":null,
         "paymentToken":null,
         "approvedBy":null,
         "approvedByUser":null,
         "approvedAt":null,
         "created_at":"2023-10-30T07:52:30.000000Z",
         "status":"pending"
      },
      {
         "id":290,
         "user":{
            "id":8,
            "userID":"yuwrgojsvIXqGeAzT18bTxbObEG3",
            "name":"Obama Clinton",
            "email":"email@user2",
            "username":"username2",
            "profilePic":"645866b914fu.jpg",
            "created_at":"2023-05-07T23:01:24.000000Z"
         },
         "userID":8,
         "groupID":28,
         "paymentDueDate":"2023-11-01",
         "paymentDate":"2023-10-30",
         "amount":1000,
         "forDuration":"November",
         "proofOfPayment":null,
         "paymentMode":"MobileMoney",
         "paymentID":"5888699-999",
         "paymentToken":null,
         "approvedBy":null,
         "approvedByUser":null,
         "approvedAt":"2023-10-30 07:53:15",
         "created_at":"2023-10-30T07:52:30.000000Z",
         "status":"paid"
      }
   ]
}

现有代码

ListView.builder(
  itemCount: controller.groupPaymentResponse.value?.payments?.length ?? 0,
  itemBuilder: (BuildContext context, int index) {
    var e = controller.groupPaymentResponse.value!.payments![index];
      bool sameforDuration = false;
      if (controller.groupPaymentResponse.value!.payments![index + 1].forDuration ==
        controller.groupPaymentResponse.value!.payments![index]) {
            bool sameforDuration = true;
        }
      var image = e.user!.profilePic == null ? userPlaceHolder : "${e.user!.imagePath}/${e.user!.profilePic}";
      return ExpansionTile(
        title: Text(
          e.forDuration.toString(),
        ),
          children: [Text(e.user!.name!), Text(e.user!.email!), Text(e.amount.toString())],
      );
      }),

问题分析

  • 直接遍历每条支付记录,每条都生成一个ExpansionTile,导致同月份的记录重复出现多个相同标题的Tile,无法实现分组效果。
  • sameforDuration逻辑完全无效:访问index+1会触发数组越界(当index为最后一条记录时),且比较的是整个支付对象而非forDuration字段,同时重新声明了局部变量,外层变量未被修改。
  • ExpansionTile的children仅展示单条记录的用户信息,未处理同组的多条记录。

解决方案

先将支付数据按forDuration分组,再遍历分组后的结果生成ExpansionTile,每个Tile下展示对应月份的所有用户信息。

修正后的代码

  1. 先在合适位置(如Controller或Build方法前)完成分组逻辑:
// 获取支付列表
final payments = controller.groupPaymentResponse.value?.payments ?? [];
// 按forDuration分组
final groupedPayments = <String, List<dynamic>>{};
for (final payment in payments) {
  final month = payment.forDuration ?? 'Unknown';
  if (!groupedPayments.containsKey(month)) {
    groupedPayments[month] = [];
  }
  groupedPayments[month]!.add(payment);
}
// 提取分组后的月份列表,用于ListView遍历
final months = groupedPayments.keys.toList();
  1. 修改ListView.builder:
ListView.builder(
  itemCount: months.length,
  itemBuilder: (BuildContext context, int index) {
    final month = months[index];
    final monthPayments = groupedPayments[month]!;
    
    return ExpansionTile(
      title: Text(month),
      children: monthPayments.map((payment) {
        // 用容器包裹用户信息,优化排版
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('姓名: ${payment.user!.name!}'),
              Text('邮箱: ${payment.user!.email!}'),
              Text('金额: ${payment.amount}'),
              const Divider(height: 16),
            ],
          ),
        );
      }).toList(),
    );
  },
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:04:53