DEV Community

Cover image for Exploring Simple Widgets I: The Expansion Tile
Alpha
Alpha

Posted on

Exploring Simple Widgets I: The Expansion Tile

What is the Expansion Tile Widget?

The Expansion Tile Widget is a part of the Flutter material library that allows developers to create a collapsible tile with two states: expanded and collapsed. It is widely used to create lists with items that can expand or collapse to reveal more content. This widget is particularly useful when dealing with limited screen space and the need to display additional information when required.

How does it work?

The Expansion Tile Widget consists of a header and a body. When the user taps on the header, the widget expands, revealing the content inside the body. Subsequently, another tap collapses the widget, hiding the content. Think of things like FAQ section where the answer to a question is revealed when the question tile is clicked on or a Post that reveals more info (or a comment section) when clicked.

How to use the Expansion Tile

To use the Expansion Tile Widget, simply add it to the body of your scaffold. It has a single required title parameter which takes a widget (so it could be literally any widget). It shows the title of the Expansion tile.

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expansion Tile'),
      ),
      body: Center(
        // our Expansion Tile here
        child: ExpansionTile(
          title: Text('Hey, I can Expand'),

        ),
      ) );
  }
}

Enter fullscreen mode Exit fullscreen mode

Collapsed State

Expanded State but Empty

Although we can see the change when we click on the tile, it doesn't exactly expand. That's because we haven't added the hidden items.

To add the hidden items to be revealed, we have a children property that takes in a List of widgets.

 ExpansionTile(
          title: Text('Hey, I Expand'),
          //adding the hidden items
          children: [
            ListTile(
              title: Text('Can you see me? I am a ListTile'),
              trailing: Icon(Icons.waving_hand)
            ),
             SizedBox(height: 10,),
            Text('I am a boring Text'),
            SizedBox(height: 10,),
            CircleAvatar(
              radius: 25,
              child: CircleAvatar(
                radius: 20,
                backgroundColor: Colors.white,
                child: FlutterLogo()),
            )
          ],
        ),
Enter fullscreen mode Exit fullscreen mode

Expanded state with Children

Well, that's basically all you need to do to use the ExpansionTile widget. But there are other fun stuff to play around with.
As you can see, there's a default expand more(arrow down) and expand less(arrow down) icon when we expand and collapse the tile, we can use our preferred Icon(or widget) using the trailing parameter or nothing at all by just setting the value to a SizedBox.
There's also an onExpansionChanged parameter which takes a function with a boolean param that basically tells us the state of the tile and we can do something in this function when we change the state of the tile.

class Home extends StatefulWidget {
  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  bool isExpanded = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expansion Tile'),
      ),
      body: Center(
        child: ExpansionTile(
          title: Text('Hey, I Expand'),
          trailing: Text(isExpanded ? 'close' : 'open'),
          //adding the hidden items
          onExpansionChanged: (val){
            setState((){
              isExpanded = val;
            });
          },
          children: [
            ListTile(
              title: Text('Can you see me? I am a ListTile'),
              trailing: Icon(Icons.waving_hand)
            ),
             SizedBox(height: 10,),
            Text('I am a boring Text'),
            SizedBox(height: 10,),
            CircleAvatar(
              radius: 25,
              child: CircleAvatar(
                radius: 20,
                backgroundColor: Colors.white,
                child: FlutterLogo()),
            )
          ],
        ),
      ) );
  }
}
Enter fullscreen mode Exit fullscreen mode

Collapsed tile with custom trailing

Expanded tile with custom trailing

In the snippet above, we changed our Home to a stateful widget so we could update our trailer from open to closed using setState((){}) when the tile changes.

There are other interesting attributes in the Expansion tile which includes boolean values intiallyExpanded for specifying the initial state of the tile and maintainState to specify whether the children widget be kept in the widget tree or recreated each time the tile is Expanded.
There is also the tilePadding for specifying the padding of the Expansion tile and childrenPadding for the children's padding.
Other values are provided are for styling our ExpansionTile includes such as the colors and shapes.

Here's a full list of all its Attributes:

(new) ExpansionTile ExpansionTile({
  Key? key,
  Widget? leading,
  required Widget title,
  Widget? subtitle,
  void Function(bool)? onExpansionChanged,
  List<Widget> children = const <Widget>[],
  Widget? trailing,
  bool initiallyExpanded = false,
  bool maintainState = false,
  EdgeInsetsGeometry? tilePadding,
  CrossAxisAlignment? expandedCrossAxisAlignment,
  Alignment? expandedAlignment,
  EdgeInsetsGeometry? childrenPadding,
  Color? backgroundColor,
  Color? collapsedBackgroundColor,
  Color? textColor,
  Color? collapsedTextColor,
  Color? iconColor,
  Color? collapsedIconColor,
  ShapeBorder? shape,
  ShapeBorder? collapsedShape,
  Clip? clipBehavior,
  ListTileControlAffinity? controlAffinity,
})
Enter fullscreen mode Exit fullscreen mode

Nesting Expansion Tiles

A common question that comes to mind is whether we can nest multiple expansion tiles in each other.Yes we can! However, while this is possible, it is advisable to limit the depth of the nesting to avoid overwhelming the user and to maintain a clear interface.

class Home extends StatefulWidget {
  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  bool isExpanded = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expansion Tile'),
      ),
      body: Center(
        child: Column(
          children: [
            ExpansionTile(
              controlAffinity: ListTileControlAffinity.trailing,
              title: Text('Hey, I Expand'),
              initiallyExpanded: true,
              maintainState: true,
              subtitle: Text('Click me'),
              trailing: Text(isExpanded ? 'close' : 'open'),
              //adding the hidden items
              onExpansionChanged: (val){
                setState((){
                  isExpanded = val;
                });
              },
              children: [
                ListTile(
                  title: Text('Can you see me? I am a ListTile'),
                  trailing: Icon(Icons.waving_hand)
                ),
                 SizedBox(height: 10,),
                Text('I am a boring Text'),
                SizedBox(height: 10,),
                CircleAvatar(
                  radius: 25,
                  child: CircleAvatar(
                    radius: 20,
                    backgroundColor: Colors.white,
                    child: FlutterLogo()),
                )
              ],
            ),
            ExpansionTile(
  title: Text('Parent Tile'),
  children: [
    ExpansionTile(
      title: Text('Child Tile 1'),
      children: [
        ListTile(
          title: Text('Content 1'),
        ),
      ],
    ),
    ExpansionTile(
      title: Text('Child Tile 2'),
      children: [
        ListTile(
          title: Text('Content 2'),
        ),
      ],
    ),
  ],
)
          ],
        ),
      ) );
  }
}

Enter fullscreen mode Exit fullscreen mode

Multiple Expansion Tiles

Nested Expansion Tile depth 1

Nested Expansion Tile depth 2

Conclusion

The Expansion Tile Widget in Flutter provides developers with a powerful tool to create collapsible and expandable content areas, enhancing user experience and improving UI design. By customizing the widget's appearance and behaviour, developers can create intuitive and engaging interfaces for their Flutter applications.

Checkout an interesting use of Expansion Tile in the GitHub gist below:
Github Gist

Please suggest in the comment what Widget I should look into next. Thank you

Top comments (1)

Collapse
 
laposhstylez profile image
Laposhstylez

Detailed explanations