Kinda Code
Home/Flutter/Flutter: ExpansionPanelList and ExpansionPanelList.radio examples

Flutter: ExpansionPanelList and ExpansionPanelList.radio examples

Last updated: August 19, 2023

Below are two examples of implementing ExpansionPanelList and ExpansionPanelList.radio in Flutter.

Basic ExpansionPanelList

This example creates a panel list in which multiple panels can be expanded at the same time. If you want only a single panel can be opened at once, see the second example.

Example Preview

The Code

The complete code with explanations:

// main.dart
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // Remove the debug banner
        debugShowCheckedModeBanner: false,
        title: 'Kindacode.com',
        theme: ThemeData(
          primarySwatch: Colors.indigo,
        ),
        home: const HomePage());
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // Generating some dummy data
  final List<Map<String, dynamic>> _items = List.generate(
      20,
      (index) => {
            'id': index,
            'title': 'Item $index',
            'description':
                'This is the description of the item $index. There is nothing important here. In fact, it is meaningless.',
            'isExpanded': false
          });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Kindacode.com'),
      ),
      body: SingleChildScrollView(
        child: ExpansionPanelList(
          elevation: 3,
          // Controlling the expansion behavior
          expansionCallback: (index, isExpanded) {
            setState(() {
              _items[index]['isExpanded'] = !isExpanded;
            });
          },
          animationDuration: const Duration(milliseconds: 600),
          children: _items
              .map(
                (item) => ExpansionPanel(
                  canTapOnHeader: true,
                  backgroundColor:
                      item['isExpanded'] == true ? Colors.amber : Colors.white,
                  headerBuilder: (_, isExpanded) => Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 15, horizontal: 30),
                      child: Text(
                        item['title'],
                        style: const TextStyle(fontSize: 20),
                      )),
                  body: Container(
                    padding: const EdgeInsets.symmetric(
                        vertical: 15, horizontal: 30),
                    child: Text(item['description']),
                  ),
                  isExpanded: item['isExpanded'],
                ),
              )
              .toList(),
        ),
      ),
    );
  }
}

ExpansionPanelList.radio

You can use the ExpansionPanelList.radio constructor to build an expansion panel list that has a maximum of only one panel that can be opened at a time. When you expand a new panel, the old expanded panel will be automatically collapsed. The logic is handled by Flutter, and you don’t need to add your own expansionCallback function if you don’t have a special need. Therefore, the code is simpler and neater.

Example Preview

The Code

The full code with explanations:

// main.dart
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // Remove the debug banner
        debugShowCheckedModeBanner: false,
        title: 'Kindacode.com',
        theme: ThemeData(
          primarySwatch: Colors.indigo,
        ),
        home: const HomePage());
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // Generating some dummy data
  final List<Map<String, dynamic>> _items = List.generate(
      20,
      (index) => {
            'id': index,
            'title': 'Item $index',
            'description':
                'This is the description of the item $index. There is nothing important here. In fact, it is meaningless.',
          });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Kindacode.com'),
      ),
      body: SingleChildScrollView(
        child: ExpansionPanelList.radio(
          elevation: 3,
          animationDuration: const Duration(milliseconds: 600),
          children: _items
              .map(
                (item) => ExpansionPanelRadio(
                  value: item['id'],
                  canTapOnHeader: true,
                  headerBuilder: (_, isExpanded) => Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 15, horizontal: 30),
                      child: Text(
                        item['title'],
                        style: const TextStyle(fontSize: 20),
                      )),
                  body: Container(
                    padding: const EdgeInsets.symmetric(
                        vertical: 15, horizontal: 30),
                    child: Text(item['description']),
                  ),
                ),
              )
              .toList(),
        ),
      ),
    );
  }
}

Final Words

We’ve gone through a few examples of using the ExpansionPanelList widget. If you’d like to learn more new and interesting things in Flutter, take a look at the following articles:

You can also take a tour around our Flutter topic page and Dart topic page to see the latest tutorials and examples.