sliver_expansion_tile
A Flutter sliver widget that mimics ExpansionTile
, allowing items within a CustomScrollView
to expand and collapse as a sliver.
This was part of the talk The Dark Arts of RenderSliver: Mastering Custom Slivers in Flutter at Fluttercon USA 2024.
Features
- Expand/collapse content inside a sliver list
- Fully customizable header, border, and border radius
- Programmatic control via
SliverExpansionTileController
- Smooth animation with adjustable duration
- No external dependencies beyond Flutter SDK
Getting Started
Installation
Add the latest version of sliver_expansion_tile
to your pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
sliver_expansion_tile: ^<latest_version>
Then run:
flutter pub get
Import
import 'package:sliver_expansion_tile/sliver_expansion_tile.dart';
Usage
Wrap your sliver content in a SliverExpansionTile
:
CustomScrollView(
slivers: [
SliverAppBar(title: Text('Sliver Expansion Tile')),
// A normal sliver list above
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text(items[index])),
childCount: items.length,
),
),
// The expandable tile
SliverExpansionTile(
title: Text('More Colors'),
subtitle: Text('Tap to expand'),
leading: Icon(Icons.palette),
children: [
for (final color in colorList)
Container(
height: 60,
color: color,
),
],
border: BorderSide(color: Colors.grey.shade300, width: 2),
borderRadius: Radius.circular(8),
),
// Additional slivers...
],
);
Example
See the example directory for a complete demo, including programmatic expansion/collapse using SliverExpansionTileController
:
final controller = SliverExpansionTileController();
// In your build:
SliverExpansionTile(
controller: controller,
title: Text('Controlled Tile'),
children: [ /* ... */ ],
);
// Elsewhere (e.g. in a FAB):
FloatingActionButton(
child: Icon(Icons.expand_more),
onPressed: () => controller.expand(),
),
API Reference
SliverExpansionTile
Property | Type | Description |
---|---|---|
title |
Widget |
Primary widget displayed in the header |
subtitle |
Widget? |
Optional subheader below the title |
leading |
Widget? |
Optional widget displayed before the title |
trailing |
Widget? |
Custom widget displayed after the title (defaults to arrow) |
children |
List<Widget> |
Widgets revealed when tile is expanded |
initiallyExpanded |
bool |
Whether the tile is expanded on first build (default: false) |
controller |
SliverExpansionTileController? |
Controller for programmatic expansion/collapse |
border |
BorderSide? |
Optional border drawn around expanded area |
borderRadius |
Radius |
Corner radius applied to the clip and border (default: zero) |
SliverExpansionTileController
Control the expansion state from code:
final controller = SliverExpansionTileController();
// Expand
controller.expand();
// Collapse
controller.collapse();
// Toggle
controller.toggle();
// Check state
if (controller.isExpanded) { ... }
You can also retrieve the controller from the widget tree:
final controller = SliverExpansionTileController.of(context);
Customization
- Animation duration: Modify the
AnimationController
duration by forking the package or submitting a feature request. - Theming: The tile header uses your app’s
ThemeData.colorScheme.onSurface
colors by default. Override thetitleColor
to change background or text colors.
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/fooBar
) - Commit your changes (
git commit -am 'Add some fooBar'
) - Push to the branch (
git push origin feature/fooBar
) - Open a pull request
Please ensure all tests pass and follow the effective Dart style guide.
License
This project is licensed under the MIT License. See the LICENSE file for details.