Flutter Expansion Panel

Creating expandable and collapsible content

🔽 What is Expansion Panel?

ExpansionPanel creates collapsible sections that expand to reveal more content. It's great for FAQs, settings menus, or organizing information in a compact, user-friendly way.


// Simple ExpansionPanelList
ExpansionPanelList(
  children: [
    ExpansionPanel(
      headerBuilder: (context, isExpanded) {
        return Text('Title');
      },
      body: Text('Content'),
    ),
  ],
)
                                    

Expansion Panel Components

📋

ExpansionPanelList

Container for panels

ExpansionPanelList(
  expansionCallback: (index, isExpanded) {
    // Handle expansion
  },
  children: [],
)
🎯

ExpansionPanel

Individual panel item

ExpansionPanel(
  headerBuilder: (context, isExpanded) {
    return Text('Header');
  },
  body: Text('Body'),
  isExpanded: false,
)
📝

headerBuilder

Builds panel header

headerBuilder: (context, isExpanded) {
  return ListTile(
    title: Text('Title'),
  );
}
📄

body

Panel content

body: Container(
  padding: EdgeInsets.all(16),
  child: Text('Details here'),
)

🔹 Basic Expansion Panel Example

Create a simple FAQ with expandable panels:

import 'package:flutter/material.dart';

class Item {
  String header;
  String body;
  bool isExpanded;

  Item(this.header, this.body, this.isExpanded);
}

class MyExpansionPanel extends StatefulWidget {
  @override
  _MyExpansionPanelState createState() => _MyExpansionPanelState();
}

class _MyExpansionPanelState extends State<MyExpansionPanel> {
  List<Item> items = [
    Item('What is Flutter?', 'Flutter is a UI toolkit for building apps.', false),
    Item('Is Flutter free?', 'Yes, Flutter is completely free and open-source.', false),
    Item('What languages does Flutter use?', 'Flutter uses Dart programming language.', false),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('FAQ')),
      body: SingleChildScrollView(
        child: ExpansionPanelList(
          expansionCallback: (int index, bool isExpanded) {
            setState(() {
              items[index].isExpanded = !isExpanded;
            });
          },
          children: items.map<ExpansionPanel>((Item item) {
            return ExpansionPanel(
              headerBuilder: (BuildContext context, bool isExpanded) {
                return ListTile(
                  title: Text(item.header),
                );
              },
              body: ListTile(
                title: Text(item.body),
              ),
              isExpanded: item.isExpanded,
            );
          }).toList(),
        ),
      ),
    );
  }
}

Output:

What is Flutter?
Is Flutter free?
What languages does Flutter use?

🔹 Styled Expansion Panel

Create a more visually appealing expansion panel:

ExpansionPanelList(
  elevation: 2,
  expandedHeaderPadding: EdgeInsets.all(0),
  expansionCallback: (int index, bool isExpanded) {
    setState(() {
      items[index].isExpanded = !isExpanded;
    });
  },
  children: items.map<ExpansionPanel>((Item item) {
    return ExpansionPanel(
      backgroundColor: Colors.blue[50],
      headerBuilder: (BuildContext context, bool isExpanded) {
        return ListTile(
          leading: Icon(Icons.help_outline, color: Colors.blue),
          title: Text(
            item.header,
            style: TextStyle(
              fontWeight: FontWeight.bold,
              color: Colors.blue[900],
            ),
          ),
        );
      },
      body: Container(
        padding: EdgeInsets.all(16),
        color: Colors.white,
        child: Text(
          item.body,
          style: TextStyle(fontSize: 14),
        ),
      ),
      isExpanded: item.isExpanded,
    );
  }).toList(),
)

Output:

What is Flutter?
Flutter is a UI toolkit for building apps.

🔹 ExpansionTile Alternative

Use ExpansionTile for simpler expandable content:

class SimpleExpansion extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        ExpansionTile(
          leading: Icon(Icons.person),
          title: Text('Account Settings'),
          children: [
            ListTile(
              title: Text('Change Password'),
              leading: Icon(Icons.lock),
            ),
            ListTile(
              title: Text('Update Email'),
              leading: Icon(Icons.email),
            ),
          ],
        ),
        ExpansionTile(
          leading: Icon(Icons.notifications),
          title: Text('Notifications'),
          children: [
            SwitchListTile(
              title: Text('Push Notifications'),
              value: true,
              onChanged: (bool value) {},
            ),
            SwitchListTile(
              title: Text('Email Notifications'),
              value: false,
              onChanged: (bool value) {},
            ),
          ],
        ),
      ],
    );
  }
}

Output:

👤 Account Settings
🔔 Notifications

🔹 Expansion Panel Best Practices

Tips for using Expansion Panels:

  • Use ExpansionTile for simpler cases
  • Keep headers concise - Clear and descriptive
  • Manage state properly - Track expanded state
  • Add visual feedback - Icons or colors for expanded state
  • Consider SingleChildScrollView for many panels

🧠 Test Your Knowledge

Which widget is simpler for basic expandable content?