I am using a BottomNavigationBar together with a TabController. By clicking on the different Tabs of the BottomNavigationBar the TabView is changing the content. However if I swipe on the TabView to switch to another view/tab the BottomNavigationBar is not updating to the tab I swiped to. I already have added a listener to the TabController to detect changes. But how can I update BottomNavigationBar programmatically to reflect the change?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
I think it is way more elegant to use PageView
instead of TabBarView
specially in your case.
class BottomBarExample extends StatefulWidget {
@override
_BottomBarExampleState createState() => new _BottomBarExampleState();
}
class _BottomBarExampleState extends State<BottomBarExample> {
int _page = 0;
PageController _c;
@override
void initState(){
_c = new PageController(
initialPage: _page,
);
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
bottomNavigationBar: new BottomNavigationBar(
currentIndex: _page,
onTap: (index){
this._c.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
},
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(icon: new Icon(Icons.supervised_user_circle), title: new Text("Users")),
new BottomNavigationBarItem(icon: new Icon(Icons.notifications), title: new Text("Alerts")),
new BottomNavigationBarItem(icon: new Icon(Icons.email), title: new Text("Inbox")),
],
),
body: new PageView(
controller: _c,
onPageChanged: (newPage){
setState((){
this._page=newPage;
});
},
children: <Widget>[
new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.supervised_user_circle),
new Text("Users")
],
),
),
new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.notifications),
new Text("Alerts")
],
),
),
new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.mail),
new Text("Inbox")
],
),
),
],
),
);
}
}
回答2:
you should update the current index of bottomNavigationBar to match the new index of tabview when you swipe on the TabView
class _TabBarWithBottomNavBarState extends State<TabBarWithBottomNavBar> with SingleTickerProviderStateMixin {
int _bottomNavBarIndex = 0;
TabController _tabController;
void _tabControllerListener(){
setState(() {
_bottomNavBarIndex = _tabController.index;
});
}
@override
void initState() {
_tabController = TabController(length: 3, vsync: this);
_tabController.addListener(_tabControllerListener);
super.initState();
}
@override
void dispose() {
_tabController.dispose();
_tabController.removeListener(_tabControllerListener);
super.dispose();
}
回答3:
For who is looking for a short solution here is mine, maybe it will be useful for someone:
class App extends StatefulWidget {
@override
State<StatefulWidget> createState() => AppState();
}
class AppState extends State<App> {
int currentTab = 0;
void _selectTab(int index) {
debugPrint (" index = $index ");
setState(() {
currentTab = index;
});
switch (currentTab) {
case 0:
debugPrint (" my index 0 ");
break;
case 1:
debugPrint (" my index 1 ");
break;
case 2:
debugPrint (" my index 2 ");
break;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _buildBody(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: _selectTab,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.message), title: Text("Message"),
),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text("Settings"),
),
],
),
);
}
Widget _buildBody() {
// return a widget representing a page
}
}
And we dont forget the main, should be like this:
import 'package:flutter/material.dart';
import 'App.dart';
void main() {
runApp( MaterialApp(
home: App(),
)
);
}