Flutter 可扩展的 Listview

Flutter Expandable Listview

提问人:Mbebwo 提问时间:11/2/2023 最后编辑:Mbebwo 更新时间:11/2/2023 访问量:96

问:

我有下面的对象列表,这些对象试图制作成一个按月分组的可扩展列表。这是列表中的一个值。

{
   "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",
         
      }
   ]
}

我正在尝试创建一个基于“forDuration”的颤振可扩展列表。因此,对于每个“forDuration”,我应该有该期间所有用户的姓名、电子邮件和金额的子项。我有下面的 Listview.builder 代码,但它没有显示扩展磁贴。 请帮忙。以下是我尝试过的,但结果不如预期。

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())],
      );
      }),
JSON的 扑动 列表 飞镖 颤动-getx

评论


答:

1赞 Wai Han Ko 11/2/2023 #1

您需要修改(分组)列表才能获得此结果

您可以在 dartpad 中运行它,我已经对其进行了编码,只需单击该链接即可。输出如下截图

import 'package:flutter/material.dart';
import "package:collection/collection.dart";

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Map<String, List<TestingObj>> groupedItemMap;

  List<TestingObj> testingItems = [
    TestingObj(
      "Book",
      "100000",
      "November",
    ),
    TestingObj(
      "Pencil",
      "100",
      "November",
    ),
    TestingObj(
      "Eraser",
      "1000",
      "December",
    ),
    TestingObj(
      "Ruler",
      "100000",
      "September",
    ),
    TestingObj(
      "Bag",
      "100000",
      "September",
    ),
    TestingObj(
      "Paper",
      "100000",
      "September",
    ),
  ];

  @override
  void initState() {
    groupedItemMap = groupBy(testingItems, (entry) => entry.month);

    print(groupedItemMap.toString());

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
          itemBuilder: (context, index) => ExpansionTile(
                title: Text(
                  groupedItemMap.entries.elementAt(index).key,
                ),
                children: groupedItemMap.entries
                    .elementAt(index)
                    .value
                    .map((item) => Text(item.itemName))
                    .toList(),
              ),
          itemCount: groupedItemMap.length),
    );
  }
}

class TestingObj {
  final String itemName;
  final String profit;
  final String month;

  TestingObj(this.itemName, this.profit, this.month);
}

Result images

评论

0赞 Mbebwo 11/2/2023
感谢您的帮助。但是,我遇到了一些错误。似乎需要先将地图转换为有序列表。查看我的完整代码:dartpad.dev/?372f0d5cbdde877b87600daaa9d5c44e
0赞 Usama Jamil 11/2/2023 #2

这是一个可展开的列表视图示例

main.dart

import 'package:expanded_listview_demo/subCategory.dart';
import 'package:flutter/material.dart';
import 'dataModel.dart';


void main() {
  runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}
 
 
class _MyAppState extends State<MyApp> {
  List<Menu> data = [];
 
  @override
  void initState() {
    dataList.forEach((element) {
      data.add(Menu.fromJson(element));
    });
    super.initState();
  }
  @override
   Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        drawer: _drawer(data),
        appBar: AppBar(
          title: const Text('Expandable ListView'),
        ),
        body: ListView.builder(
          itemCount: data.length,
          itemBuilder: (BuildContext context, int index) =>
              _buildList(data[index]),
        ),
      ),
    );
  }
 
  Widget _drawer (List<Menu> data){
    return Drawer(
        child: SafeArea(
          child: SingleChildScrollView(
            child: Column(
              children: [
                UserAccountsDrawerHeader(margin: EdgeInsets.only(bottom: 0.0),
                    accountName: Text('demo'), accountEmail: Text('[email protected]')),
                ListView.builder(
                  shrinkWrap: true,
                  physics: NeverScrollableScrollPhysics(),
                  itemCount: data.length,
                  itemBuilder:(context, index){return _buildList(data[index]);},)
              ],
            ),
          ),
        ));
  }
 
  Widget _buildList(Menu list) {
    if (list.subMenu.isEmpty)
      return Builder(
        builder: (context) {
          return ListTile(
              onTap:() => Navigator.push(context, MaterialPageRoute(builder: (context) => SubCategory(list.name))),
              leading: SizedBox(),
              title: Text(list.name)
          );
        }
      );
    return ExpansionTile(
      leading: Icon(list.icon),
      title: Text(
        list.name,
        style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
      ),
      children: list.subMenu.map(_buildList).toList(),
    );
  }
}

DataModel 类

import 'package:flutter/material.dart';
 
List dataList = [
  {
    "name": "Sales",
    "icon": Icons.payment,
    "subMenu": [
      {"name": "Orders"},
      {"name": "Invoices"}
    ]
  },
  {
    "name": "Marketing",
    "icon": Icons.volume_up,
    "subMenu": [
      {
        "name": "Promotions",
        "subMenu": [
          {"name": "Catalog Price Rule"},
          {"name": "Cart Price Rules"}
        ]
      },
      {
        "name": "Communications",
        "subMenu": [
          {"name": "Newsletter Subscribers"}
        ]
      },
      {
        "name": "SEO & Search",
        "subMenu": [
          {"name": "Search Terms"},
          {"name": "Search Synonyms"}
        ]
      },
      {
        "name": "User Content",
        "subMenu": [
          {"name": "All Reviews"},
          {"name": "Pending Reviews"}
        ]
      }
    ]
  }
];
 
class Menu {
  String name;
  IconData icon;
  List<Menu> subMenu = [];
 
  Menu({this.name, this.subMenu, this.icon});
 
  Menu.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    icon = json['icon'];
    if (json['subMenu'] != null) {
      subMenu.clear();
      json['subMenu'].forEach((v) {
        subMenu?.add(new Menu.fromJson(v));
      });
    }
  }
}