flutter - 使用底部导航栏颤动保存 PageView 内每个页面的状态
问题描述
我在堆栈中有两个主要小部件,它们放置在主路由(屏幕)内:
- 页面预览
- 底部导航
pageView 的每一页都包裹在 CustomNavigator 小部件内,导航器的键列表放置在主路由(屏幕)内。使用底部导航栏导航可以正常工作,但是当推送到页面内的另一个死记硬背并转到另一个页面并返回时,推送路由的页面状态变为默认状态,我该怎么办?这是我的主屏幕状态:
const String MainRoute = '/';
const String AccountRoute = '/account';
const String CategoriesRoute = '/categories';
const String HomeRoute = '/home';
const String WishListRoute = '/wish_list';
const String ProductRoute = '/product';
class _MainState extends State<Main> {
int _pressedPosition = 0;
final List _screenStates = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
PageView(
physics:new NeverScrollableScrollPhysics(),
controller: _pageController,
children: _mainScreens(),
),
Align(
alignment: Alignment.bottomCenter,
child: CurvedNavigationBar(
animationDuration: Duration(milliseconds: 200),
backgroundColor: Colors.transparent,
onTap: (int position) {
_bottomTapped(position);
},
height: 60.0,
items: <Widget>[...],
),
)
],
),
);
}
PageController _pageController = PageController(
initialPage: 0,
keepPage: true,
);
void _bottomTapped(int index) {
setState(() {
_pressedPosition = index;
_pageController.animateToPage(index,
duration: Duration(milliseconds: 300), curve: Curves.ease);
});
}
List<Widget> _mainScreens() {
return <Widget>[
CustomNavigator(initialRoute: HomeView(), navigatorKey: _screenStates[0],),
CustomNavigator(initialRoute: CategoriesView(), navigatorKey: _screenStates[1],),
CustomNavigator(initialRoute: ShoppingCartView(), navigatorKey: _screenStates[2],),
CustomNavigator(initialRoute: WishListView(), navigatorKey: _screenStates[3],),
CustomNavigator(initialRoute: AccountView(), navigatorKey: _screenStates[4],),
];
}
这是自定义导航器类:
class CustomNavigator extends StatelessWidget {
final Widget initialRoute;
final GlobalKey<NavigatorState> navigatorKey;
CustomNavigator({@required this.initialRoute, @required this.navigatorKey});
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
onGenerateRoute: _routes(initialRoute),
);
}
//routing
RouteFactory _routes(Widget initialRoute) {
return (settings) {
final Map<String, dynamic> arguments = settings.arguments;
Widget screen;
switch (settings.name) {
case MainRoute:
screen = initialRoute;
break;
case ProductRoute:
screen = ProductView();
break;
default:
return null;
}
return MaterialPageRoute(builder: (BuildContext context) => screen);
};
}
}
我已经阅读了https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386,https://medium.com/@Mr_Pepe/nested-navigation-with-a- bottom-navigation-bar-using-flutter-d3c5086fbcdc和http://bizz84.github.io/2018/07/07/Multiple-Navigators-BottomNavigationBar.html但无论如何这些主题都难以理解。
另外找到了这个解决方案,但它不起作用:https ://github.com/indatawetrust/nested-navigation-demo-flutter
帮助!谢谢))
解决方案
PageView 卸载不可见的选项卡以节省内存,这就是您的状态丢失的原因。KeepAlive
但是你可以通过使用机器来强迫他们留下来。请参阅AutomaticKeepAliveClientMixin
执行此操作的最简单方法。这应该适用于与标签一起使用的 PageView。您可以使用IndexedStack
而不是PageView
因为它不会卸载小部件,它只是在其他小部件之上显示当前活动的小部件。IndexedStack 中的每个小部件都返回自己的导航器,就像您目前正在做的那样。所以您可以做这样的事情
IndexedStack(
index: _pressedPosition,
children: _mainScreens(), //return Views Here
),
)
然后点击
setState(() {
_pressedPosition = index;
});
您可以使用BottomNavigationBar
它是 Scaffold 小部件的一部分,并为此目的而制作。检查此链接以供参考(导航部分)。
推荐阅读
- r - 根据多个匹配修改映射表
- parsing - 使用 attoparsec 更有效地解析 Haskell 中的句子
- python - 在python中用变量填充字典的优雅方法
- java - 带有按钮和 GUI 的 Java
- javascript - NodeJS - 收到错误“发送后无法设置标题”
- python-3.x - python不在模式x下创建文件
- c++ - C ++将排列结果插入向量
- python - 在同一个 Api 视图中更新和删除,而不在 Url 中传递 id
- homebrew - 在 Travis CI 上缓存 Homebrew 瓶和配方
- jquery-select2 - 选择 2 未选择的选项