如果我们在 GetX 上使用 bottomNavigationBar,如何使用内部导航

Posted

技术标签:

【中文标题】如果我们在 GetX 上使用 bottomNavigationBar,如何使用内部导航【英文标题】:how to use inner navigation if we using bottomNavigationBar on GetX 【发布时间】:2021-04-17 02:58:19 【问题描述】:

我正在尝试在小部件的 body 内部进行导航,bottomNavigationBar 仍然在外面,这是我的代码:

class WrapperController extends GetxController 
  int currentIndex = 0;
  List<BottomNavigationElement> items = [];

  Widget navigationTab(GlobalKey<NavigatorState> naviKey, Widget widget) 
    return Navigator(
      key: naviKey,
      onGenerateRoute: (routeSettings) 
        return GetPageRoute(page: () => widget);
      ,
    );
  

  Widget bottomNavigationBar() 
    return BottomNavigationBar(
      selectedItemColor: Get.theme.accentColor,
      type: BottomNavigationBarType.fixed,
      currentIndex: currentIndex,
      backgroundColor: Get.theme.primaryColor,
      onTap: (int index) => _selectTab(index),
      items: items.map((e) => e.bottomBarItem).toList(),
    );
  

  void _selectTab(int index) 
    if (index == currentIndex) 
      items[index]
          .navigationKey
          .currentState
          .popUntil((route) => route.isFirst);
     else 
      currentIndex = index;
    
    update();
  

  Future<bool> onWillPop() async 
    final isFirstRouteInCurrentTab =
        !await items[currentIndex].navigationKey.currentState.maybePop();
    if (isFirstRouteInCurrentTab) 
      if (currentIndex != 0) 
        // _selectTab(1);
        return false;
      
    
    return isFirstRouteInCurrentTab;
  

  @override
  void onInit() 
    super.onInit();
    items = [
      //Каталог
      BottomNavigationElement(
        bottomBarItem: BottomNavigationBarItem(
          icon: Icon(Icons.search),
          label: "Home",
        ),
        bottomBarView: HomePage(),
        navigationKey: Get.nestedKey('0'),
      ),
      //Любимое
      BottomNavigationElement(
        bottomBarItem: BottomNavigationBarItem(
          icon: Icon(Icons.favorite_border),
          label: "Favorites",
        ),
        bottomBarView: FavoritesPage(),
        navigationKey: Get.nestedKey('1'),
      ),
      //Корзина
      BottomNavigationElement(
        bottomBarItem: BottomNavigationBarItem(
          icon: Icon(Icons.shopping_cart_outlined),
          label: "Cart",
        ),
        bottomBarView: CartPage(),
        navigationKey: Get.nestedKey('2'),
      ),
      //Заказы
      BottomNavigationElement(
        bottomBarItem: BottomNavigationBarItem(
          icon: Icon(Icons.history),
          label: "History",
        ),
        bottomBarView: HistoryPage(),
        navigationKey: Get.nestedKey('3'),
      ),
      //Меню
      BottomNavigationElement(
        bottomBarItem: BottomNavigationBarItem(
          icon: Icon(Icons.menu),
          label: "Menu",
        ),
        bottomBarView: MenuPage(),
        navigationKey: Get.nestedKey('4'),
      ),
    ];
  


class BottomNavigationElement 
  Widget bottomBarView;
  BottomNavigationBarItem bottomBarItem;
  GlobalKey<NavigatorState> navigationKey;
  BottomNavigationElement(
    @required this.bottomBarView,
    @required this.bottomBarItem,
    @required GlobalKey<NavigatorState> navigationKey,
  );

这里是Wrapper 小部件:

class Wrapper extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return GetBuilder<WrapperController>(builder: (controller) 
      return Scaffold(
        body: IndexedStack(
          index: controller.currentIndex,
          children: controller.items
              .map((e) => controller.navigationTab(
                    naviKey: e.navigationKey,
                    widget: e.bottomBarView,
                  ))
              .toList(),
        ),
        bottomNavigationBar: controller.bottomNavigationBar(),
      );
    );
  

这里是HomePage("Search"),它有一个导航按钮:

class HomePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Home"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) => Detail(),
            ),
          ),
          child: Text("Detail"),
        ),
      ),
    );
  

问题是,当我改用Navigator.of (context) Get.to () 时,导航是完全完成的,而不是在正文中。我需要使用Get.to () 进行内部导航,我该怎么做?

【问题讨论】:

【参考方案1】:

有一个快速的解决方案

    为底部导航栏创建一个单独的导航器(如果您想将身份验证与主逻辑分开)。

    代码如下:

    Expanded(
                child: Navigator(
                key: Get.nestedKey(1),
                initialRoute: controller.pageName.value,
                onGenerateRoute: HomeRouter.generateRoute,
              )
    )
    

    导航

    void gotoPage(String page, BuildContext context) 
        pageName.value = page;
        print("Request to go to $pageName.value");
        Get.keys[1]!.currentState!.pushNamed(page);
        //if you want to change the URL in browser as well
        html.window.history.pushState(null, "/", page);
      
    

【讨论】:

以上是关于如果我们在 GetX 上使用 bottomNavigationBar,如何使用内部导航的主要内容,如果未能解决你的问题,请参考以下文章

flutter 完全使用GetX 主题切换 以及 自创建Widget的颜色随主题变化方案

使用 GetX 改变主题?

Flutter中GetX系列六--GetxController使用详情

在flutter中使用getX打开页面时自动调整页面语言

如何使用 GetX 包管理 Flutter Web URL 路由?

Flutter GetX基础教程(十二):RxList、Rx([])、.obs对比分析