Во Flutter 3.32 появился новый виджет - Expansible. Он пришел на смену старому ExpansionTile и его контроллеру, который больше не поддерживается. Давайте разберем на простом примере, как он работает.
Что такое Expansible:
Expansible - это StatefulWidget, который умеет плавно раскрываться и сворачиваться. У него есть две части:
🔵header - заголовок, который всегда на виду.
🔵body - содержимое, которое появляется при раскрытии.
Анимацией управляет AnimationController, поэтому все работает плавно и без дерганий, в отличие от старого ExpansionTile.
Простой пример:
Самый частый сценарий - когда по тапу на заголовок раскрывается дополнительный контент. Вот как это выглядит:
class ExpansibleExample extends StatefulWidget {
@override
State<ExpansibleExample> createState() => _ExpansibleExampleState();
}
class _ExpansibleExampleState extends State<ExpansibleExample> {
final _controller = ExpansibleController();
@override
Widget build(BuildContext context) {
return Expansible(
controller: _controller,
headerBuilder: (context, animation) => ListTile(
title: Text('Нажми, чтобы раскрыть'),
onTap: () {
if (_controller.isExpanded) {
_controller.collapse();
} else {
_controller.expand();
}
},
trailing: RotationTransition(
turns: Tween<double>(begin: 0.0, end: 0.5).animate(animation),
child: Icon(Icons.arrow_drop_down),
),
),
bodyBuilder: (context, animation) => SizeTransition(
sizeFactor: animation,
child: Text('А вот и скрытый контент!'),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Обратите внимание на несколько важных моментов. Во-первых, ExpansibleController нужно создавать и не забывать вызывать dispose(). Во-вторых, для плавного поворота стрелочки используется animation, которая приходит в headerBuilder - она уже содержит нужное значение от 0 до 0.5 оборота. В-третьих, SizeTransition с animation анимирует высоту body. Все вместе дает аккуратный эффект без лишних телодвижений.
Важный нюанс про ListView:
Если вы используете Expansible внутри ListView или SingleChildScrollView, обязательно передавайте PageStorageKey. Иначе при скролле виджет будет терять свое состояние (раскрыт или свернут) и пользователь удивится.
Expansible(
key: PageStorageKey('unique_key_1'), // каждому Expansible свой ключ
controller: _controller,
headerBuilder: ...
bodyBuilder: ...
)
🔗 Читать подробнее
💡 Вывод:
Expansible - это не просто замена устаревшему виджету. Это инструмент, который решает давнюю боль Flutter-разработчиков: плавная анимация высоты, сохранение состояния при скролле и чистый API через контроллер. Пример выше можно скопировать и вставить в любой проект - он работает из коробки. А если нужно больше гибкости, подключайте expansibleBuilder и настраивайте под свои задачи. Если вы обновились до Flutter 3.32, присмотритесь к этому виджету - он реально удобнее.
Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик
Закрытый канал:
🚀 Мобильный трудоголик PRO