@override bool get wantKeepAlive => true;
但發現需要配合其他組件,不是隨便mixin就有用的,嘗試幾種寫法總結BottomNavigationBar+List+AutomaticKeepAliveClientMixin是沒有用的
- 首先嘗試BottomNavigationBar+List實現的頁面切換保持狀態,一般剛開始學都會這么寫:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(
title: "demo",
home: MainPage(),
);
}
class MainPage extends StatefulWidget {
@override
StatecreateState() => MainPageState();
}
class MainPageState extends State{
int _currentIndex;
List_pages;
@override
void initState() {
super.initState();
_currentIndex = 0;
_pages = List()..add(FirstPage("第一頁"))..add(SecondPage("第二頁"))..add(ThirdPage("第三頁"));
}
@override
Widget build(BuildContext context) => Scaffold(
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
items: getItems(),
currentIndex: _currentIndex,
onTap: onTap,
),
);
ListgetItems() {
return [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Home")),
BottomNavigationBarItem(icon: Icon(Icons.adb), title: Text("Adb")),
BottomNavigationBarItem(icon: Icon(Icons.person), title: Text("Person"))
];
}
void onTap(int index) {
setState(() {
_currentIndex = index;
});
}
}
子頁面代碼,三個界面一樣:
class FirstPage extends StatefulWidget {
String _title;
FirstPage(this._title);
@override
StatecreateState() => FirstPageState();
}
class FirstPageState extends Statewith AutomaticKeepAliveClientMixin{
int _count = 0;
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget._title),
),
body: Center(
child: Text(widget._title + ":點一下加1:$_count"),
),
floatingActionButton: FloatingActionButton(
heroTag: widget._title, child: Icon(Icons.add), onPressed: add),
);
}
void add() {
setState(() {
_count++;
});
}
}
結果無法實現保持頁面
第一個.
2.第二種BottomNavigationBar+PageView,與android的ViewPager類似,界面小改動一下,添加一個按鈕,點擊跳轉到一個新的界面
代碼如下:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(
title: "demo",
home: MainPage(),
);
}
class MainPage extends StatefulWidget {
@override
StatecreateState() => MainPageState();
}
class MainPageState extends State{
int _currentIndex;
List_pages;
PageController _controller;
@override
void initState() {
super.initState();
_currentIndex = 0;
_pages = List() ..add(FirstPage("第一頁")) ..add(SecondPage("第二頁")) ..add(ThirdPage("第三頁"));
_controller = PageController(initialPage: 0);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) => Scaffold(
body: PageView.builder(
physics: NeverScrollableScrollPhysics(),//viewPage禁止左右滑動
onPageChanged: _pageChange,
controller: _controller,
itemCount: _pages.length,
itemBuilder: (context, index) => _pages[index]),
bottomNavigationBar: BottomNavigationBar(
items: getItems(),
currentIndex: _currentIndex,
onTap: onTap,
),
);
ListgetItems() {
return [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Home")),
BottomNavigationBarItem(icon: Icon(Icons.adb), title: Text("Adb")),
BottomNavigationBarItem(icon: Icon(Icons.person), title: Text("Person"))
];
}
void onTap(int index) {
_controller.jumpToPage(index);
}
void _pageChange(int index) {
setState(() {
if (index != _currentIndex) {
_currentIndex = index;
}
});
}
}
子界面:
class FirstPage extends StatefulWidget {
String _title;
FirstPage(this._title);
@override
StatecreateState() => FirstPageState();
}
class FirstPageState extends Statewith AutomaticKeepAliveClientMixin {
int _count = 0;
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget._title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:[
Text(widget._title + ":點一下加1:$_count"),
MaterialButton(
child: Text("跳轉"),
color: Colors.pink,
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => NewPage())))
],
),
),
floatingActionButton: FloatingActionButton(
heroTag: widget._title, child: Icon(Icons.add), onPressed: add),
);
}
void add() {
setState(() {
_count++;
});
}
}
需要跳轉的一個界面:
class NewPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text("新的界面"),
),
body: Center(
child: Text("我是一個新的界面"),
),
);
}
2.
猛一看效果出來了,左右切換界面沒有問題,結果跳轉新界面時又出現新問題,當第一頁跳轉新的界面再返回,再切第二、三頁發現重置了,再切回第一頁發現頁被重置了。
發生這種情況需要在重寫Widget build(BuildContext context)時調用下父類build(context)方法,局部代碼:
@override
Widget build(BuildContext context) {
//在這邊加上super.build(context);
super.build(context);
return Scaffold(
appBar: AppBar(
title: Text(widget._title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:[
Text(widget._title + ":點一下加1:$_count"),
MaterialButton(
child: Text("跳轉"),
color: Colors.pink,
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => NewPage())))
],
),
),
floatingActionButton: FloatingActionButton(
heroTag: widget._title, child: Icon(Icons.add), onPressed: add),
);
}
第三個.
這種布局樣式網上還有一種用的比較多的是BottomNavigationBar+Stack+Offstage,這邊就不貼出來了
- 最近發現最好的實現是BottomNavigationBar+TabBarView,
BottomNavigationBar+ PageView的話如果給PageView加翻頁動畫話的第一頁直接切換第三頁,翻頁動畫不是很流暢,因為是第一頁翻到第三頁,而TabBarView切換起來就非常完美
class IndexPage extends StatefulWidget {
@override
_IndexPageState createState() => _IndexPageState();
}
class _IndexPageState extends Statewith SingleTickerProviderStateMixin {
TabController _controller;
ListbottomTabs;
int _currentIndex = 0;
@override
void initState() {
super.initState();
bottomTabs = List()
..add(_buildBottomNavItem("assets/images/index_phone_unselect.png",
"assets/images/index_phone_select.png", "首頁"))
..add(_buildBottomNavItem("assets/images/index_package_unselect.png",
"assets/images/index_package_select.png", "包啊"))
..add(_buildBottomNavItem("assets/images/index_found_unselect.png",
"assets/images/index_found_select.png", "發現"))
..add(_buildBottomNavItem("assets/images/index_person_unselect.png",
"assets/images/index_person_select.png", "我的"));
_controller = TabController(length: bottomTabs.length, vsync: this);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
fixedColor: Color(0xFF333333),
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
onTap: _bottomNavBarClick,
items: bottomTabs),
body: TabBarView(
physics: NeverScrollableScrollPhysics(), //禁止滾動
controller: _controller,
children: [
PhonePage(),
PackagePage(),
FoundPage(),
PersonalPage(),
]),
);
}
_bottomNavBarClick(index) {
setState(() {
_currentIndex = index;
});
_controller.animateTo(_currentIndex);
}
BottomNavigationBarItem _buildBottomNavItem(
String icon, String activeIcon, String name) {
double height = 28.0, width = 28.0;
return BottomNavigationBarItem(
icon: Image.asset(icon, height: height, width: width),
activeIcon: Image.asset(activeIcon, height: height, width: width),
title: Text(name));
}
}
最后像這種多頁面使用FloatingActionButton,用它跳轉新界面是一定要設置heroTag,要不然跳轉會黑屏報錯
