#flutter #tabbar
Вопрос:
Мне нужна панель вкладок и представление вкладок, как описано в https://flutter.dev/docs/cookbook/design/tabs , но есть один нюанс: мне нужна АКТИВНАЯ вкладка, чтобы показать дополнительный пользовательский виджет.
Если пользователь переключается на другую вкладку, мне нужно, чтобы пользовательский виджет исчез с ранее активной вкладки, а на новой активной вкладке появился НОВЫЙ пользовательский виджет.
Другой способ объяснить это: на всех вкладках должен быть размещен экземпляр моего пользовательского виджета, но пользовательские виджеты должны быть скрыты на всех, кроме активной вкладки.
Как этого добиться, пожалуйста?
Большое спасибо
Ответ №1:
Все дело в управлении состоянием. Я сделал пример использования AnimatedBuilder
с помощью a TabController
, но вы можете настроить его в соответствии с вашими потребностями.
Имейте в виду: думайте декларативно, это поможет вам создать экран любого типа с любой бизнес-логикой.
Шаги:
- Получить текущий индекс
- Прослушивание изменений текущего индекса на всех вкладках
- Проверьте, соответствует ли индекс вкладки текущему выбранному индексу
- Если это так, отобразите пользовательский виджет
- В противном случае просто игнорируйте, ничего не создавайте
import 'package:flutter/material.dart';
void main() {
runApp(const TabBarDemo());
}
class TabBarDemo extends StatefulWidget {
const TabBarDemo({Key? key}) : super(key: key);
@override
_TabBarDemoState createState() => _TabBarDemoState();
}
class _TabBarDemoState extends State<TabBarDemo>
with SingleTickerProviderStateMixin {
late final TabController _controller;
@override
void initState() {
super.initState();
_controller = TabController(length: 3, vsync: this, initialIndex: 0);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _controller,
tabs: [
Tab(
child: AnimatedBuilder(
animation: _controller,
builder: (context, chiild) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.directions_car),
if (_controller.index == 0) const MyCustomWidget(),
],
);
},
),
),
Tab(
child: AnimatedBuilder(
animation: _controller,
builder: (context, chiild) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.directions_transit),
if (_controller.index == 1) const MyCustomWidget(),
],
);
},
),
),
Tab(
child: AnimatedBuilder(
animation: _controller,
builder: (context, chiild) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.directions_bike),
if (_controller.index == 2) const MyCustomWidget(),
],
);
},
),
),
],
),
title: const Text('Tabs Demo'),
),
body: TabBarView(
controller: _controller,
children: const [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
);
}
}
class MyCustomWidget extends StatelessWidget {
const MyCustomWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: const Text('Your CustomWidget'),
);
}
}
Комментарии:
1. Спасибо, очень полезно. Есть ли способ, чтобы каждый MyCustomWidget () определял для себя индекс активной вкладки, чтобы он мог показывать / скрывать себя? Это позволит избежать повторяющегося кода «if (_controller.index == xxxx) const MyCustomWidget()» на каждой вкладке
2. Я должен был сказать «индекс активной вкладки И ее собственный индекс»
3. Да, вы можете добавить цикл for для построения каждой вкладки, и вы будете использовать индекс цикла вместо необработанного индекса, такого как 0, 1, 3, …
Ответ №2:
Tab( )
виджет может содержать любой виджет, а не только Text
и icon
Сначала вам нужно определить, какая вкладка была выбрана.
Затем вам нужно выполнить «если» (?), Чтобы решить, какой виджет отображать.
Используйте этот код:
int selectedTab=1;
TabBar(
onTap: (index) {
selectedTab = index;
},
tabs: [
Tab(
child: (selectedTab == 1) ? yourCustomWidget1 : yourWidget1
),
Tab(
child: (selectedTab == 2) ? yourCustomWidget2 : yourWidget2
),
]);
Дайте мне знать, если это не сработает
Комментарии:
1. Спасибо, это полезно, но я почти уверен, что onTap() не сработает, если пользователь проведет пальцем по панели вкладок, чтобы перейти на другую вкладку?