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:
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:
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.
EDIT2: Got It, there was a line commented out in the CustomExpansionTile!
Output:
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(),
)
],
);
}
}