source: https://www.canva.com/
You must have seen this interaction in many of the apps.
Expansion panel list is a list that shows its children using expansion animation on click of item.
1ExpansionPanelList(
2 expansionCallback: (int index, bool isExpanded) {},
3 children: [
4 ExpansionPanel(
5 headerBuilder: (BuildContext context, bool isExpanded) {
6 return ListTile(
7 title: Text('Item 1'),
8 );
9 },
10 body: ListTile(
11 title: Text('Item 1 child'),
12 subtitle: Text('Details goes here'),
13 ),
14 isExpanded: true,
15 ),
16 ExpansionPanel(
17 headerBuilder: (BuildContext context, bool isExpanded) {
18 return ListTile(
19 title: Text('Item 2'),
20 );
21 },
22 body: ListTile(
23 title: Text('Item 2 child'),
24 subtitle: Text('Details goes here'),
25 ),
26 isExpanded: false,
27 ),
28 ],
29);
➊ expansionCallBack:
This gets called whenever the expand/collapsed button is pressed on any of the items inside the list.
It gives us two things.
➋ children:
ExpansionPanel widget is used as a child for the ExpansionPanelList. This widget has got below properties.
➌ animationDuration:
Used to define the duration in which the expand and collapsed animation should complete. It defaults to 200ms.
However, it is recommended to keep it to the original you can still change it to anything like this.
1animationDuration: Duration(milliseconds: 300),
The basic code above won’t actually expand/collapse. That was just a starter code to make things clear before we move on.
So how do we actually make it work? Here are the steps.
➊ Create a class that will hold the data for the item.
1class Item {
2 Item({
3 this.expandedValue,
4 this.headerValue,
5 this.isExpanded = false,
6 });
7
8 String expandedValue;
9 String headerValue;
10 bool isExpanded;
11}
bool isExpanded will be used to determine whether the item needs to expand or not.
➋ Prepare a list of items.
1List<Item> generateItems(int numberOfItems) {
2 return List.generate(numberOfItems, (int index) {
3 return Item(
4 headerValue: 'Book $index',
5 expandedValue: 'Details for Book $index goes here',
6 );
7 });
8}
9
10List<Item> _books = generateItems(8);
➌ Map each item in the list to ExpansionPanel because we are going to use it as a child for the ExpansionPanelList and not the Item itself.
1children: _books.map<ExpansionPanel>((Item item) {
2 return ExpansionPanel();
3}).toList(),
➍ On receiving expansionCallback change the isExpanded parameter of the item inside the list of books and rebuild a widget.
1expansionCallback: (int index, bool isExpanded) {
2 setState(() {
3 _books[index].isExpanded = !isExpanded;
4 });
5},
Click on RunPen to read and play with the code
Thanks for reading. If you found this article to be helpful please share it with your friends.
Also read - Four Essential Types of ListView in Flutter and How to Utilize Them.