Flutter Expandable ListView Example

In this tutorial, We are going to learn how we can create expandable listview in flutter applications. Expandable listview is used to expand or collapse view in list items.

When we have not enough space to display all data then expandable listview is best option. We can also classify data under various categories using expandable listview.

In this example, We are going to display football data. We will display league names at root level. In each league, we will display popular football clubs. Under each club, We will display football players which are associated with that club.

 

Create Required Classes

First We create league class. In this class, we are passing league name and associated clubs. In club class, we are passing club name and associated players same as parent league class. In player class, We are only passing player name because there is no other sub level data.

class League {
    String leagueName;
    List<Club> listClubs;

    League(this.leagueName, this.listClubs);
}

class Club {
    String clubName;
    List<Player> listPlayers;

    Club(this.clubName, this.listPlayers);
}

class Player {
    String playerName;

    Player(this.playerName);
}

 
 

Add Multilevel Data For Flutter Expandable ListView

We are adding five football leagues in list. In each league, we are adding associated clubs and their players as below.

final List<League> data = <League>[
League(
    ‘Premier League’,
    <Club>[
        Club(
            ‘Liverpool’,
            <Player>[
                Player(‘Virgil van Dijk’),
                Player(‘Mohamed Salah’),
                Player(‘Sadio Mané’),
            ],
        ),
        Club(
            ‘Manchester City’,
            <Player>[
                Player(‘Kevin De Bruyne’),
                Player(‘Sergio Aguero’),
            ],
        ),
    ],
),
League(
    ‘La Liga’,
    <Club>[
        Club(
            ‘Real Madrid’,
            <Player>[
                Player(‘Sergio Ramos’),
                Player(‘Karim Benzema’),
            ],
        ),
        Club(
            ‘Barcelona’,
            <Player>[
                Player(‘Lionel Messi’),
            ],
        ),
    ],
),
League(
    ‘Ligue One’,
    <Club>[
        Club(
            ‘Paris Saint-Germain’,
            <Player>[
                Player(‘Neymar Jr.’),
                Player(‘Kylian Mbappé’),
            ],
        ),
    ],
),
League(
    ‘Bundeshliga’,
    <Club>[
        Club(
            ‘Bayern Munich’,
            <Player>[
                Player(‘Robert Lewandowski’),
                Player(‘Manuel Neuer’),
            ],
        ),
    ],
),
];
 
 

Create Widget For Flutter Expandable ListView

We can collapse or expand view using ExpansionTile widget. This widget has different properties like key, title, children etc. key property defines widget type. We can customize header view using title property. children property defines widgets which are displayed when tile expands.

class MyExpandableWidget extends StatelessWidget {
final League league;

MyExpandableWidget(this.league);

@override
Widget build(BuildContext context) {
    if (league.listClubs.isEmpty)
    return ListTile(title: Text(league.leagueName));
    return ExpansionTile(
        key: PageStorageKey<League>(league),
        title: Text(league.leagueName, style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Colors.pinkAccent)),
        children: league.listClubs
        .map<Widget>((club) => showClubs(club))
        .toList(),
    );
}
}

showClubs(Club club) {
    return new ExpansionTile(
        key: PageStorageKey<Club>(club),
        title: Text(club.clubName, style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.purpleAccent),),
        children: club.listPlayers.map<Widget>((player) => showPlayers(player)).toList(),
    );
}

showPlayers(Player player) {
    return new ListTile(
        title: new Text(player.playerName, style: new TextStyle(fontSize: 20),
    ),
);
}

 
 

Add ListView Widget

ListView.builder(
    itemBuilder: (BuildContext context, int index) =>
    MyExpandableWidget(data[index]),
    itemCount: data.length,
),
 
 

Final Code

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyHomePage(title: 'Flutter Expandable List Sample'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<League> data = <League>[
    League(
      'Premier League',
      <Club>[
        Club(
          'Liverpool',
          <Player>[
            Player('Virgil van Dijk'),
            Player('Mohamed Salah'),
            Player('Sadio Mané'),
          ],
        ),
        Club(
          'Manchester City',
          <Player>[
            Player('Kevin De Bruyne'),
            Player('Sergio Aguero'),
          ],
        ),
      ],
    ),
    League(
      'La Liga',
      <Club>[
        Club(
          'Real Madrid',
          <Player>[
            Player('Sergio Ramos'),
            Player('Karim Benzema'),
          ],
        ),
        Club(
          'Barcelona',
          <Player>[
            Player('Lionel Messi'),
          ],
        ),
      ],
    ),
    League(
      'Ligue One',
      <Club>[
        Club(
          'Paris Saint-Germain',
          <Player>[
            Player('Neymar Jr.'),
            Player('Kylian Mbappé'),
          ],
        ),
      ],
    ),
    League(
      'Bundeshliga',
      <Club>[
        Club(
          'Bayern Munich',
          <Player>[
            Player('Robert Lewandowski'),
            Player('Manuel Neuer'),
          ],
        ),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemBuilder: (BuildContext context, int index) =>
            MyExpandableWidget(data[index]),
        itemCount: data.length,
      ),
    );
  }
}

class MyExpandableWidget extends StatelessWidget {
  final League league;

  MyExpandableWidget(this.league);

  @override
  Widget build(BuildContext context) {
    if (league.listClubs.isEmpty)
      return ListTile(title: Text(league.leagueName));
    return ExpansionTile(
      key: PageStorageKey<League>(league),
      title: Text(league.leagueName, style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Colors.pinkAccent)),
      children: league.listClubs
          .map<Widget>((club) => showClubs(club))
          .toList(),
    );
  }
}

showClubs(Club club) {
  return new ExpansionTile(
    key: PageStorageKey<Club>(club),
    title: Text(club.clubName, style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.purpleAccent),),
    children: club.listPlayers.map<Widget>((player) => showPlayers(player)).toList(),
  );
}

showPlayers(Player player) {
  return new ListTile(
    title: new Text(
      player.playerName,
      style: new TextStyle(fontSize: 20),
    ),
  );
}

class League {
  String leagueName;
  List<Club> listClubs;

  League(this.leagueName, this.listClubs);
}

class Club {
  String clubName;
  List<Player> listPlayers;

  Club(this.clubName, this.listPlayers);
}

class Player {
  String playerName;

  Player(this.playerName);
}
 
 
 
flutter expandable listview