#flutter #flutter-layout #tabbar
#flutter #flutter-макет #панель вкладок
Вопрос:
У меня дизайн, подобный описанному выше, моя панель вкладок находится внутри BottomNavigationBar, и я хочу разместить панель вкладок в моем меню BottomNavigationBar. Проблема в том, что я не хочу иметь вложенный каркас, и я не хочу использовать TabController
потому что мои вкладки динамические, длина вкладок может уменьшаться или увеличиваться в зависимости от добавления пользователя. Если я использую TabController
и определяю его внутри initState
, вкладки не могут быть увеличены / уменьшены, потому что в initState значение определяется только один раз.
Как я могу это сделать?
Мое ожидание, аналогичное приведенному ниже примеру, когда я добавляю вкладку и tabMenu, оно увеличится. Но получаю эту ошибку
The following assertion was thrown building TabBar(dirty, dependencies: [_InheritedTheme,
_LocalizationsScope-[GlobalKey#a56a4]], state: _TabBarState#fb337):
Controller's length property (2) does not match the number of tabs (3) present in TabBar's tabs
property.
The relevant error-causing widget was:
TabBar
Фиктивный пример
class TaskScreen extends StatefulWidget {
@override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen> with SingleTickerProviderStateMixin {
TabController _tabController;
final List<Tab> _tab = [
Tab(text: 'Sunday'),
Tab(text: 'Monday'),
];
final List<Widget> _tabMenu = [
Text('This is Sunday'),
Text('This is Monday'),
];
@override
void initState() {
super.initState();
_tabController = TabController(length: _tab.length, vsync: this);
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlatButton(
onPressed: () {
setState(() {
_tab.add(Tab(
text: '1',
));
_tabMenu.add(Text('1'));
});
print('tab ${_tab.length}');
print('tabMenu ${_tabMenu.length}');
},
child: Text('add')),
Container(
color: colorPallete.primaryColor,
padding: EdgeInsets.only(top: sizes.statusBarHeight(context)),
child: TabBar(
tabs: _tab.map((e) => e).toList(),
controller: _tabController,
),
),
Expanded(
child: TabBarView(
children: _tabMenu.map((e) => e).toList(),
controller: _tabController,
),
)
],
);
}
}
Ответ №1:
используйте TickerProviderStateMixin
вместо SingleTickerProviderStateMixin
и измените TabController
при изменении количества вкладок;
добавляйте isScrollable: true
, когда у вас нет места для всех ваших вкладок
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return TaskScreen();
}
}
class TaskScreen extends StatefulWidget {
@override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen> with TickerProviderStateMixin {
TabController _tabController;
final List<Tab> _tab = [
Tab(text: 'Sunday'),
Tab(text: 'Monday'),
];
final List<Widget> _tabMenu = [
Text('This is Sunday'),
Text('This is Monday'),
];
@override
void initState() {
super.initState();
_tabController = TabController(length: _tab.length, vsync: this);
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlatButton(
onPressed: () {
setState(() {
_tab.add(
Tab(
text: '1',
),
);
_tabMenu.add(
Text('1'),
);
_tabController =
TabController(length: _tab.length, vsync: this);
});
print('tab ${_tab.length}');
print('tabMenu ${_tabMenu.length}');
},
child: Text('add')),
Container(
color: Colors.blue,
padding: EdgeInsets.only(top: 10),
child: TabBar(
// isScrollable: true,
tabs: _tab.map((e) => e).toList(),
controller: _tabController,
),
),
Expanded(
child: TabBarView(
children: _tabMenu.map((e) => e).toList(),
controller: _tabController,
),
)
],
);
}
}