Here is a simple example for creating expanded list in flutter.
Watch Video Tutorial
We will create a new class named “Entry” which will be the data on each row of the list.
class Entry { final String title; final List<Entry> children; // Since this is an expansion list ...children can be another list of entries Entry(this.title, [this.children = const <Entry>[]]); }
Data Source
Let’s create the array to be shown in the expanded list.
// This is the entire multi-level list displayed by this app final List<Entry> data = <Entry>[ Entry( 'Chapter A', <Entry>[ Entry( 'Section A0', <Entry>[ Entry('Item A0.1'), Entry('Item A0.2'), Entry('Item A0.3'), ], ), Entry('Section A1'), Entry('Section A2'), ], ), // Second Row Entry('Chapter B', <Entry>[ Entry('Section B0'), Entry('Section B1'), ]), Entry( 'Chapter C', <Entry>[ Entry('Section C0'), Entry('Section C1'), Entry( 'Section C2', <Entry>[ Entry('Item C2.0'), Entry('Item C2.1'), Entry('Item C2.2'), Entry('Item C2.3'), ], ) ], ), ];
Create Row Widget
// Create the Widget for the row class EntryItem extends StatelessWidget { const EntryItem(this.entry); final Entry entry; // This function recursively creates the multi-level list rows. Widget _buildTiles(Entry root) { if (root.children.isEmpty) { return ListTile( title: Text(root.title), ); } return ExpansionTile( key: PageStorageKey<Entry>(root), title: Text(root.title), children: root.children.map<Widget>(_buildTiles).toList(), ); } @override Widget build(BuildContext context) { return _buildTiles(entry); } }
Create the List
ListView.builder( itemCount: data.length, itemBuilder: (BuildContext context, int index) => EntryItem( data[index], ), ),
That’s it.
Complete code
import 'package:flutter/material.dart'; class ExpansionTileDemo extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Expansion List'), ), body: ListView.builder( itemCount: data.length, itemBuilder: (BuildContext context, int index) => EntryItem( data[index], ), ), ), ); } } // Welcome to another flutter tutorial // In this video we will see how to create a multi-level Expansion List // First Let's create a class for each row in the Expansion List class Entry { final String title; final List<Entry> children; // Since this is an expansion list ...children can be another list of entries Entry(this.title, [this.children = const <Entry>[]]); } // This is the entire multi-level list displayed by this app final List<Entry> data = <Entry>[ Entry( 'Chapter A', <Entry>[ Entry( 'Section A0', <Entry>[ Entry('Item A0.1'), Entry('Item A0.2'), Entry('Item A0.3'), ], ), Entry('Section A1'), Entry('Section A2'), ], ), // Second Row Entry('Chapter B', <Entry>[ Entry('Section B0'), Entry('Section B1'), ]), Entry( 'Chapter C', <Entry>[ Entry('Section C0'), Entry('Section C1'), Entry( 'Section C2', <Entry>[ Entry('Item C2.0'), Entry('Item C2.1'), Entry('Item C2.2'), Entry('Item C2.3'), ], ) ], ), ]; // Create the Widget for the row class EntryItem extends StatelessWidget { const EntryItem(this.entry); final Entry entry; // This function recursively creates the multi-level list rows. Widget _buildTiles(Entry root) { if (root.children.isEmpty) { return ListTile( title: Text(root.title), ); } return ExpansionTile( key: PageStorageKey<Entry>(root), title: Text(root.title), children: root.children.map<Widget>(_buildTiles).toList(), ); } @override Widget build(BuildContext context) { return _buildTiles(entry); } }
hi. thank you for your sharing.this helped me a lot. i have a question, how to make title/substitle clickable? I’ve tried wrap inside a gesture detector and inkwell widget but still doesnt work. it would be nice if you can help me by making a tutorial or sample coding on how to make it onTap/clickable. looking forward for your response. thank you 🙂
Make sure you don’t have another Gesture Detector for the ListRow which may block the gesture detector inside it.
I need an help with, how to make multi level list as dynamic, here in this case it is hard coded.