`ExpansionTileController` is deprecated. The same functionality can be achieved by using `ExpansibleController` instead.
- Who is affected
- Code that still calls the deprecated API; it keeps working until removal but produces analyzer warnings. Code that uses ExpansionTileController, ExpansibleController, ExpansionTile and related APIs.
- Practical impact
- Warnings now; removal in a future release. Plan the migration but no immediate break.
- What action should I take?
- Follow the official migration guide below, update affected call sites, run `dart fix --apply` where a fix is available, then run your tests.
Before and after (from the official guide)
| 1 | class _MyWidgetState extends State<MyWidget> { | |
| 2 | − | final ExpansionTileController controller = ExpansionTileController(); |
| 3 | ||
| 4 | @override | |
| 5 | Widget build(BuildContext context) { | |
| 6 | return ExpansionTile( | |
| 7 | controller: controller, | |
| 8 | ); | |
| 9 | } | |
| 10 | } |
| 1 | class _MyWidgetState extends State<MyWidget> { | |
| 2 | + | final ExpansibleController controller = ExpansibleController(); |
| 3 | ||
| 4 | @override | |
| 5 | + | void dispose() { |
| 6 | + | controller.dispose(); |
| 7 | + | super.dispose(); |
| 8 | + | } |
| 9 | + | |
| 10 | + | @override |
| 11 | Widget build(BuildContext context) { | |
| 12 | return ExpansionTile( | |
| 13 | controller: controller, | |
| 14 | ); | |
| 15 | } | |
| 16 | } |
Raw before / after
class _MyWidgetState extends State<MyWidget> {
final ExpansionTileController controller = ExpansionTileController();
@override
Widget build(BuildContext context) {
return ExpansionTile(
controller: controller,
);
}
}class _MyWidgetState extends State<MyWidget> {
final ExpansibleController controller = ExpansibleController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ExpansionTile(
controller: controller,
);
}
}Official migration guide (excerpt, © The Flutter Authors, CC BY 3.0)
To migrate, replace the controller parameter of an ExpansionTile from an ExpansionTileController to an ExpansibleController. Unlike ExpansionTileController, ExpansibleController is a ChangeNotifier, so remember to dispose the new ExpansibleController.
Code before migration:
class _MyWidgetState extends State<MyWidget> {
final ExpansionTileController controller = ExpansionTileController();
@override
Widget build(BuildContext context) {
return ExpansionTile(
controller: controller,
);
}
}Code after migration:
class _MyWidgetState extends State<MyWidget> {
final ExpansibleController controller = ExpansibleController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ExpansionTile(
controller: controller,
);
}
}AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.Listed in the official breaking-changes index; title states deprecation.
An official announcement or migration guide documents an intended behaviour or API change. A verified source change (git diff) shows code changed but does not by itself prove a public API is breaking. AI interpretations are labelled and never used to classify a change.
- Official migration guide
- ExpansibleController
- Expansible.controller
- Codeshare between ExpansionTile and its Cupertino variant
- Deprecate ExpansionTileController in favor of ExpansibleController
- Introduce Expansible, a base widget for ExpansionTile
- Deprecate ExpansionTileController
- Source commit
- b3045439b7c0
- Source last updated
- Oct 21, 2026
- Last synchronized
- Oct 21, 2026
- Publication status
- published
Publication history
- Oct 21, 2026, 8:31 PM: new → published (ingestion) — Backed by an official breaking-change/migration guide.
AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.