Expansion Tile Open/Close Demo
This demo shows you how to open an expansion tile while simultaneously closing an already open tile while maintaining animation using the Expansion Tile widget.
Getting Started
Flutter 3.0.6-0.0.pre.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7ce44f121f (13 days ago) • 2022-08-19 14:37:55 -0500
Engine • revision e85ea0e79c
Tools • Dart 2.17.6 • DevTools 2.12.2
Clone the repository to your dev pc. Inside the lib directory you will see two files:
- main.dart
- expansion_tile_copy.dart
expansion_tile_copy.dart File
- This file contains a copy of the Flutter source code for the expansion tile. The only difference is that we changed the class name to "ExpansionTileCopy" and added two methods to the state class:
// Added to class
void closeExpansion() {
if (_isExpanded) _handleTap();
}
// Added to class
void openExpansion() {
if (!_isExpanded) _handleTap();
}
- These methods will allow us to open/close the specified expansion tile. We are only going to be using the closeExpansion method for this project.
main.dart File
final _tileKeys = [];
var _selectedIndex = 0;
- The code above is added top level to allow for global access outside of the class. Can be contained within the class if for isolated use.
- The _tileKeys list stores the GlobalKeys assigned to each expansion tile.
- The _selectedIndex variable stores the index of the currently opened expansion tile.
ListView.separated(
itemBuilder: (context, index) {
final tileKey = GlobalKey();
_tileKeys.add(tileKey); // <- Add tile key to [_tileKeys] list.
return ExpansionTileCopy(
key: tileKey, // <- Add a key to each tile.
title: Text("Tile $index"),
children: [
Container(
color: Colors.grey[350],
height: 200,
child: Center(
child: Text("Tile $index Body"),
))
],
onExpansionChanged: (value) {
// If tile is expanding, then collapse the already expanded tile.
if (value) {
if (index != _selectedIndex) {
_tileKeys[_selectedIndex].currentState!.closeExpansion();
}
_selectedIndex = index;
}
},
);
},
separatorBuilder: (context, index) => const Divider(height: 0),
itemCount: 100));
- Each generated GlobalKey is stored in the _tileKeys list.
- The generated GlobalKey is assigned to the ExpansionTileCopy key field.
- In the onExpansionChanged callback function, we check if the value is true, which indicates the tile is opening. We only want to execute the block if we are expanding another tile. If the index of the tile being expanded does not equal the _selectedIndex value, then we want to fetch the GlobalKey for the currently expanded tile by it's index, which is represented by the _selectedIndex value. Once the GlobalKey is obtained, we then execute the closeExpansion method that we added to the ExpansionTileCopy state class.
- This will collapse the currently expanded tile, while expanding the tile that was just clicked on.
- We then assign the new index to the _selectedIndex variable.