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下展示对应月份的所有用户信息。
修正后的代码
- 先在合适位置(如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();
- 修改
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
相关产品推荐
相关产品推荐

