如何在 Flutter 的底部导航中处理后退导航

Posted

技术标签:

【中文标题】如何在 Flutter 的底部导航中处理后退导航【英文标题】:How to handle back navigation in Bottom Navigation in Flutter 【发布时间】:2020-12-17 22:32:15 【问题描述】:

我正在制作一个颤振应用程序,其中流程是这样的:启动画面,它将检查用户是否登录。如果未登录,则转到登录屏幕,否则转到主屏幕。主屏幕具有三个选项卡的底部导航,每个选项卡都有自己的导航器,在每个导航器中,某些屏幕可能不会显示底部栏。所以我一直编码到现在。

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter',
      home: Splash(),
      routes: <String, WidgetBuilder>
        '/main_tab':  (context) => new MainScreen(),
         '/login':  (context) => new Login(),
      ,
    );
  


现在有底部标签的 MainScreen 是这样的。

class MainScreen extends StatefulWidget 
  @override
  _MainScreenState createState() => new _MainScreenState();


class _MainScreenState extends State<MainScreen>
  final _navigatorKey = GlobalKey<NavigatorState>();
  int _selectedIndex = 0;
  int _lastIndex = 0;

  void _onItemTapped(int index) 
     if(index == 0) _navigatorKey.currentState.pushNamed('/');
     else if(index == 1) _navigatorKey.currentState.pushNamed('/page1');
     else if(index == 2) _navigatorKey.currentState.pushNamed('/page2');
    setState(() 
      _lastIndex = _selectedIndex;
      _selectedIndex = index;
    );
  
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: WillPopScope(
        onWillPop: () async 
          if(_selectedIndex == 0) SystemNavigator.pop();
          else if (_navigatorKey.currentState.canPop()) 
             _navigatorKey.currentState.pop();
             setState(() 
               _selectedIndex = _lastIndex;
              // _lastIndex = _selectedIndex;
             );
              return false;
           
          return true;
        ,
        child: Navigator(
          key: _navigatorKey,
          initialRoute: '/',
            onGenerateRoute: (RouteSettings settings) 
              WidgetBuilder builder;
              // Manage your route names here
              switch (settings.name) 
                case '/':
                  builder = (BuildContext context) => Page1();
                  break;
                case '/page1':
                  builder = (BuildContext context) => Page2();
                  break;
                case '/page2':
                  builder = (BuildContext context) => Page3();
                  break;
                default:
                  throw Exception('Invalid route: $settings.name');
              
              return MaterialPageRoute(
                builder: builder,
                settings: settings,
              );
            
        ),
      ),
      bottomNavigationBar:BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            title: Text('Business'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            title: Text('School'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
        type: BottomNavigationBarType.fixed,
      ),
    );
  

根据我的要求,一切正常。要导航到没有底栏的屏幕,我遇到了一些问题,但我通过使用rootnavigator:true 并在MainApp() 中声明该路线来管理它。 现在,担心的是,当我按下返回按钮时,屏幕弹出工作正常,但它并没有改变底部栏选择的索引。所以我把逻辑放在 willPop 中,但那不能正常工作。 所以请告诉我如何处理底部栏中的后按,并且它应该更改底部栏的选定选项卡。

【问题讨论】:

【参考方案1】:

在我参与的一个项目中,我必须这样做。应用程序有底部导航,一些页面正在使用根导航器推送。为了处理后退动作,我这样做了:

WillPopScope(
  onWillPop: () async 
    bool canPop = await appFlows[currentTabIndex]
        .navigatorKey
        .currentState
        .maybePop();
    if (canPop) 
      return false;
    
    if (currentTabIndex != 0) 
      navigateToTab(0);
      return false;
    
    return true;
  ,
  child: ...,
)

这样,如果选项卡的导航堆栈有多个屏幕,则会弹出该屏幕。如果用户在选项卡的根屏幕并按回,用户将被发送到主选项卡。如果用户在主选项卡的根屏幕并按下回,Flutter 将处理并退出应用程序。

【讨论】:

以上是关于如何在 Flutter 的底部导航中处理后退导航的主要内容,如果未能解决你的问题,请参考以下文章

Flutter单击后退按钮时如何执行

如何在底部应用栏中使用后退按钮实现导航。安卓

使用底部应用栏标签导航 - 颤动

Flutter - 底部导航 - 如何重建页面?

Flutter 底部导航栏

如何在 2.5 版本的新 Flutter 模板上集成底部导航栏?