1

Im trying to convert my existing iOS Application into Flutter.

In iOS I'm using UICollectionViewDiffableDataSource to view a structure like that:

struct ClassItem: Hashable{
 let year: String
 let students: [StudentItem]
}

let BiologyClass = [
 ClassItem(year: "2021", students: [
  StudentItem(name: "Michael Pearson", favColor: "blue"),
  StudentItem(name: "Pearson Michael", favColor: "green")
 ]),
 ClassItem(year: "2020", students: [
  StudentItem(name: "Steve Pearson", favColor: "blue"),
  StudentItem(name: "Steve Michael", favColor: "green"),
  StudentItem(name: "Pearson Steve", favColor: "red")
 ]),

That looks like this:

iosView

In Flutter I try to work with an ExpansionPanel:

  Widget build(BuildContext context) {
    return ExpansionPanelList(
            children: [
              ExpansionPanel(
                headerBuilder: (context, isExpanded) {
                  return ListTile(
                    title: Text(
                      '2021',
                      style: TextStyle(color: Colors.black),
                    ),
                  );
                },
                body: Column(
                  children: [
                    ListTile(
                      title: Text('Description text',
                          style: TextStyle(color: Colors.black)),
                    ),
                    ListTile(
                      title: Text('Description text2',
                          style: TextStyle(color: Colors.black)),
                    ),
                  ],
                ),
                isExpanded: _expanded,
                canTapOnHeader: true,
              ),
            ],
            dividerColor: Colors.grey,
            expansionCallback: (panelIndex, isExpanded) {
              _expanded = !_expanded;
              setState(() {});
            },
      
    ); 

So the question is, how is it possible to create a variable number of Tiles within the ExpansionPanel. Or better, how is it possible to build something like shown with using UICollectionViewDiffableDataSource in iOS env. Currently I would have to create all tiles by hand and that is just not feasible in the final version. Flutter looks like this currently:

FlutterView

Thanks.

EDIT: There is an error "Duplicate Keys Found". The following image is showing the debugging window. I don't know why the entry is doubled. Debug

EDIT2: Got It, there was a line commented out in the CustomExpansionTile!

1 Answers1

0

Output:

enter image description here

Create Data Models similar to Swift structs and datasource as BiologyClass:

class ClassItem {
  ClassItem({this.isExpanded: false, this.year, this.students});

  bool isExpanded;
  final String year;
  final List<StudentItem> students;
}

class StudentItem {
  StudentItem({this.name, this.favColor});

  final String name;
  final String favColor;
}

Now you can iterate through the items and populate the ExpansionPanelList with dynamic data:

class _MyHomePageState extends State<MyHomePage> {
  List<ClassItem> _items = <ClassItem>[
    ClassItem(year: "2021", students: [
      StudentItem(favColor: "blue", name: "Michael Pearson"),
      StudentItem(favColor: "green", name: "Pearson Michael")
    ]),
    ClassItem(year: "2020", students: [
      StudentItem(favColor: "blue", name: "Steve Pearson"),
      StudentItem(favColor: "green", name: "Steve Michael"),
      StudentItem(favColor: "red", name: "Pearson Steve")
    ]),
  ];

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        ExpansionPanelList(
          expansionCallback: (int index, bool isExpanded) {
            setState(() {
              _items[index].isExpanded = !_items[index].isExpanded;
            });
          },
          children: _items.map((ClassItem item) {
            return ExpansionPanel(
              headerBuilder: (BuildContext context, bool isExpanded) {
                return Text(item.year);
              },
              isExpanded: item.isExpanded,
              body: Column(children: [
                ...item.students.map((StudentItem student) {
                  return GestureDetector(
                    onTap: () {
                      print(student.name);
                    },
                    child: Container(child: Padding(padding: const EdgeInsets.all(8.0), child: Text(student.name))),
                  );
                }).toList(),
              ]),
            );
          }).toList(),
        )
      ],
    );
  }
}
RTXGamer
  • 3,215
  • 6
  • 20
  • 29
  • Wow, that was quick. Thank you! Is it possible to set an OnTap Action for the students item? – Stanely2206 Oct 20 '21 at 22:41
  • @Stanely2206 Tap Action added, Check the updated answer. – RTXGamer Oct 20 '21 at 23:21
  • 1
    Finally, I just implemented your code, works out brilliant, thanks! – Stanely2206 Oct 29 '21 at 09:16
  • @Stanely2206 great, you can accept the answer if it worked for you. – RTXGamer Oct 29 '21 at 09:20
  • Do you know if there was a change? When I try the same code, which was running fine for the last time, I receive the following error: Duplicate Keys found - [<1>] Error is raised in ExpansionPanelList( expansionCallback: (int index, bool isExpanded) { setState(() { _items[index].isExpanded = !_items[index].isExpanded; }); – Stanely2206 Dec 01 '21 at 21:55
  • I just edited my post, I would be very happy if you will find a solution. Thanks! – Stanely2206 Dec 01 '21 at 22:15