В Flutter виджет Expansion Tile предоставляет удобный способ создания расширяемых и сворачиваемых плиток в вашем приложении. По умолчанию одновременно можно открыть несколько плиток расширения. Однако в некоторых сценариях вам может потребоваться запретить пользователю открывать только одну плитку расширения за раз. В этой статье мы рассмотрим различные методы достижения такого поведения во Flutter, а также приведем примеры кода.
Метод 1: ExpansionPanelList
Виджет ExpansionPanelList позволяет создать список расширяемых панелей. Обернув виджеты ExpansionTile в виджеты ExpansionPanel, вы можете включить возможность открытия только одной панели за раз. Вот пример:
ExpansionPanelList(
elevation: 1,
expandedHeaderPadding: EdgeInsets.zero,
children: List.generate(
items.length,
(index) => ExpansionPanel(
headerBuilder: (context, isExpanded) {
return ListTile(
title: Text('Panel ${index + 1}'),
);
},
body: ListTile(
title: Text('Content for Panel ${index + 1}'),
),
isExpanded: selectedItemIndex == index,
),
),
expansionCallback: (index, isExpanded) {
setState(() {
selectedItemIndex = isExpanded ? null : index;
});
},
)
Метод 2: IndexedStack
Виджет IndexedStack позволяет размещать несколько виджетов друг над другом и отображать только по одному в зависимости от индекса. Используя виджет IndexedStack для упаковки виджетов ExpansionTile и управления индексом, вы можете добиться желаемого поведения. Вот пример:
int selectedItemIndex = -1;
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
selectedItemIndex = index == selectedItemIndex ? -1 : index;
});
},
child: IndexedStack(
index: index == selectedItemIndex ? 1 : 0,
children: [
ListTile(
title: Text('Panel ${index + 1}'),
),
ListTile(
title: Text('Content for Panel ${index + 1}'),
),
],
),
);
},
)
Метод 3: настраиваемое управление состоянием
Если вы предпочитаете использовать собственное решение для управления состоянием, вы можете создать отдельный класс для управления состоянием плиток расширения. Вот пример:
class ExpansionTileManager {
int selectedItemIndex = -1;
void toggle(int index) {
selectedItemIndex = selectedItemIndex == index ? -1 : index;
}
bool isExpanded(int index) {
return selectedItemIndex == index;
}
}
ExpansionTileManager manager = ExpansionTileManager();
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
manager.toggle(index);
});
},
child: ExpansionTile(
title: Text('Panel ${index + 1}'),
children: [
ListTile(
title: Text('Content for Panel ${index + 1}'),
),
],
initiallyExpanded: manager.isExpanded(index),
),
);
},
)
Реализуя один из вышеперечисленных методов, вы можете гарантировать, что в вашем приложении Flutter одновременно будет открыта только одна плитка расширения. Независимо от того, решите ли вы использовать ExpansionPanelList, IndexedStack или собственный подход к управлению состоянием, конечный результат обеспечит лучшее взаимодействие с пользователем. Поэкспериментируйте с этими методами и выберите тот, который лучше всего соответствует требованиям вашего приложения.
Помните, что Flutter предоставляет широкий спектр возможностей для настройки внешнего вида и поведения плиток расширения, поэтому не стесняйтесь изучать официальную документацию Flutter для дальнейших улучшений.