使用底部导航栏抖动在PageView内保存每个页面的状态

时间:2020-08-12 06:16:16

标签: flutter dart

我在堆栈中有两个主要小部件,它们放置在主要路线(屏幕)中:

  • PageView
  • BottomNavigation

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-b3e440b9386https://medium.com/@Mr_Pepe/nested-navigation-with-a-bottom-navigation-bar-using-flutter-d3c5086fbcdchttp://bizz84.github.io/2018/07/07/Multiple-Navigators-BottomNavigationBar.html,但是无论如何,这些主题都很难理解。

另外找到了该解决方案,但它不起作用:https://github.com/indatawetrust/nested-navigation-demo-flutter

帮助!谢谢))

1 个答案:

答案 0 :(得分:0)

PageView卸载不可见的选项卡以节省内存,这就是为什么您的状态会丢失的原因。但是您可以使用KeepAlive机制来强迫他们留下来。有关最简单的方法,请参见AutomaticKeepAliveClientMixin。这应该与用于选项卡的PageView一起使用。您可以使用IndexedStack代替PageView,因为它不会卸载窗口小部件,而只会在其他窗口之上显示当前活动的窗口小部件。就像您当前正在执行的那样,IndexedStack中的每个小部件都会返回自己的导航器。因此您可以执行类似的操作

IndexedStack(
      index: _pressedPosition,
      children: _mainScreens(), //return Views Here
    ),
  )

然后单击

setState(() {
      _pressedPosition = index;
    });

您可以使用BottomNavigationBar,它是Scaffold小部件的一部分,仅用于此目的。选中此link供参考(导航部分)。