Creating Expandable and Collapsible UIs with Flutter’s ExpansionPanelList: A Practical Guide with Code Examples

Ravi PatelRavi Patel
3 min read

Introduction

User interfaces allowing users to expand and collapse content sections provide an organized and user-friendly experience. Flutter’s ExpansionPanelList widget is the perfect tool for achieving this functionality. In this blog post, we'll explore how to effectively use the ExpansionPanelList widget to build interactive and collapsible UIs in your Flutter applications, complete with practical code examples.

Getting Started: Basic Implementation

Let’s start by creating a basic ExpansionPanelList with static content. Suppose we want to display a list of frequently asked questions (FAQs) that users can expand to view answers.

import 'package:flutter/material.dart';

class ExpansionPanelListScreen extends StatefulWidget {
  const ExpansionPanelListScreen({super.key});

  @override
  State<ExpansionPanelListScreen> createState() => _ExpansionPanelListState();
}

class _ExpansionPanelListState extends State<ExpansionPanelListScreen> {
  List<Item> _data = [];

  @override
  void initState() {
    super.initState();
    _data = generateItems(5);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ExpansionPanelList'),
      ),
      body: SingleChildScrollView(
        child: Container(
          margin: const EdgeInsets.all(16.0),
          child: _buildPanel(),
        ),
      ),
    );
  }

  List<Item> generateItems(int numberOfItems) {
    return List<Item>.generate(numberOfItems, (int index) {
      return Item(
        headerValue: 'Question ${index + 1}',
        expandedValue: 'Answer ${index + 1}',
      );
    });
  }

  Widget _buildPanel() {
    return ExpansionPanelList(
      expansionCallback: (int index, bool isExpanded) {
        setState(() {
          _data[index].isExpanded = !isExpanded;
        });
      },
      children: _data.map<ExpansionPanel>((Item item) {
        return ExpansionPanel(
          headerBuilder: (BuildContext context, bool isExpanded) {
            return ListTile(
              title: Text(item.headerValue),
            );
          },
          body: ListTile(
            title: Text(item.expandedValue),
          ),
          isExpanded: item.isExpanded,
        );
      }).toList(),
    );
  }
}

class Item {
  Item({
    required this.expandedValue,
    required this.headerValue,
    this.isExpanded = false,
  });

  String expandedValue;
  String headerValue;
  bool isExpanded;
}

In this example, we’re using a ExpansionPanelList to display a list of FAQs. Users can tap on a question to expand and view the answer. The state of each panel is managed using the isExpanded property.

Customizing Panel Content and Styling

You can customize the appearance of the header and body of each panel to match your app’s design. Use headerBuilder and body properties to define custom widgets for these sections. Additionally, you can style the panels using themes.

// Inside _buildPanel()
return ExpansionPanelList(
  expansionCallback: (int index, bool isExpanded) {
    setState(() {
      _data[index].isExpanded = !isExpanded;
    });
  },
  elevation: 2, // Panel elevation
  expandedHeaderPadding: EdgeInsets.all(8.0), // Padding for expanded header
  dividerColor: Colors.grey, // Divider color between panels
  children: _data.map<ExpansionPanel>((Item item) {
    return ExpansionPanel(
      headerBuilder: (BuildContext context, bool isExpanded) {
        return ListTile(
          title: Text(
            item.headerValue,
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
        );
      },
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(item.expandedValue),
      ),
      isExpanded: item.isExpanded,
    );
  }).toList(),
);

Conclusion

Flutter’s ExpansionPanelList widget is a powerful tool for creating collapsible and interactive user interfaces. By mastering its usage and applying customization techniques, you can build dynamic and user-friendly UIs in your Flutter apps. The provided code examples serve as a starting point for creating your own expandable and collapsible content sections. With this knowledge in hand, you can enhance your app's usability and provide a seamless user experience.

0
Subscribe to my newsletter

Read articles from Ravi Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ravi Patel
Ravi Patel

"📱 Passionate Flutter Developer with 6+ years of experience, dedicated to crafting exceptional mobile applications. 🚀 Adept at turning ideas into polished, user-friendly experiences using Flutter's magic. 🎨 Design enthusiast who believes in the power of aesthetics and functionality. 🛠️ Expertise in translating complex requirements into clean, efficient code. 🌟 Committed to staying updated with the latest trends and continuously pushing boundaries. Let's create something extraordinary together!"