Android 后退按钮无法与 Flutter 选项卡内的导航器配合使用

问题描述 投票:0回答:3

我需要在每个选项卡内有一个导航器,因此当我推送新的小部件时,选项卡栏会保留在屏幕上。代码运行得很好,但是 android 后退按钮正在关闭应用程序而不是运行 Navigator.pop()

import 'package:flutter/material.dart';

void main() {
  runApp(const TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  const TabBarDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 1,
        child: Scaffold(
          bottomNavigationBar: const BottomAppBar(
            color: Colors.black,
            child: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              Navigator(
                onGenerateRoute: (settings) {
                  return MaterialPageRoute(
                    builder: (context) => IconButton(
                        icon: Icon(Icons.directions_car),
                        onPressed: () => Navigator.of(context).push(
                            MaterialPageRoute(
                                builder: (context) => newPage()))),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class newPage extends StatelessWidget {
  const newPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("new page"),
      ),
      body: Center(child: Icon(Icons.add)),
    );
  }
}

代码也可用 here 但在 dartpad 上你无法测试 Android 后退按钮。

android flutter tabs navigation
3个回答
3
投票

首先您应该为您的导航器创建一个密钥

final GlobalKey<NavigatorState> homeNavigatorKey = GlobalKey();

然后将此键添加到您的导航器中

Navigator(
      key: homeNavigatorKey,

然后将您的

Navigator
包装在
WillPopScope
小部件中,并添加
onWillPop
,如下所示

child: WillPopScope(
    onWillPop: () async {
      return !(await homeNavigatorKey.currentState!.maybePop());
    },
    child: Navigator(
      key: homeNavigatorKey,

这将检查

navigatorKey
是否可以弹出一条路线,如果是,它只会弹出此路线,如果不是,它会弹出自己,从而关闭应用程序


0
投票

基于奥马尔·哈特姆的回答

在TabBarController状态下:

final GlobalKey<NavigatorState> screenANavigatorKey = GlobalKey();
final GlobalKey<NavigatorState> screenBNavigatorKey = GlobalKey();

辅助功能:

GlobalKey<NavigatorState> indexToNavigatorKey(int index) {
  switch (index) {
    case 0: return screenANavigatorKey;
    case 1: return screenBNavigatorKey;
  }
}

WillPopScope.onWillPop

// I am saving the current screen index in some variable
GlobalKey<NavigatorState> subScreenNavigatorKey = indexToNavigatorKey(currentScreen);
await subScreenNavigatorKey.currentState?.maybePop();
return ...

WillPopScope
的孩子:

CupertinoTabScaffold(
  controller: _controller,
  tabBuilder: (context, index) =>
    CupertinoTabView(
      navigatorKey: screenToNavigatorKey(index),
      builder: (context) => // your current screen goes here

0
投票

家居集团:

GlobalKey<NavigatorState>? navigatorPage1Key;
GlobalKey<NavigatorState>? navigatorPage2Key;
GlobalKey<NavigatorState>? navigatorPage3Key;
GlobalKey<NavigatorState>? navigatorPage4Key;
GlobalKey<NavigatorState>? navigatorPage5Key;
var pageIndex = 0;

我的主页有子页面,例如 page1、page2、page3....

在主页:

return WillPopScope(
      onWillPop: () async {
        switch (homeBloc.pageIndex) {
          case 0:
            return !(await homeBloc.navigatorPage1Key!.currentState!.maybePop());
          case 1:
            return !(await homeBloc.navigatorPage2Key!.currentState!.maybePop());
          case 2:
            return !(await homeBloc.navigatorPage3Key!.currentState!.maybePop());
          case 3:
            return !(await homeBloc.navigatorPage4Key!.currentState!.maybePop());
          case 4:
            return !(await homeBloc.navigatorPage5Key!.currentState!.maybePop());
        }
        return true;
      },
      child: BlocBuilder<HomeBloc, HomeState>(
        builder: (context, state) {
          return Scaffold(
            body: Material(
              child: Column(
                children: [
                  Expanded(
                    child: Container(
                      decoration: const BoxDecoration(
                        color: AppColors.backgroundPrimary,
                      ),
                      child: IndexedStack(
                        sizing: StackFit.expand,
                        index: homeBloc.pageIndex,
                        children: <TabCustomWidget>[
                          TabCustomWidget(
                            tab: const Page1(),
                            navigatorKey: homeBloc.navigatorPage1Key,
                          ),
                          TabCustomWidget(
                            tab: const Page2(),
                            navigatorKey: homeBloc.navigatorPage2Key,
                          ),
                          TabCustomWidget(
                            tab: const Page3(),
                            navigatorKey: homeBloc.navigatorPage3Key,
                          ),
                          TabCustomWidget(
                            tab: const Page4(),
                            navigatorKey: homeBloc.navigatorPage4Key,
                          ),
                          TabCustomWidget(
                            tab: const Page5(),
                            navigatorKey: homeBloc.navigatorPage5Key,
                          ),
                        ],
                      ),
                    ),
                  ),
                  Visibility(
                    visible: state.isViewBottomNavigator,
                    child: const BottomNavigationBarWidget(),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );

基本我的

TabCustomWidget

class TabCustomWidget extends StatelessWidget {
  final Widget tab;
  final String tabKeyLogger;
  final GlobalKey<NavigatorState>? navigatorKey;
  const TabCustomWidget({
    super.key,
    required this.tab,
    required this.tabKeyLogger,
    this.navigatorKey,
  });

  @override
  Widget build(BuildContext context) {
    return CupertinoTabView(
      builder: (context) => tab,
      routes: AppRoutes.routes,
      navigatorKey: navigatorKey,
      navigatorObservers: [RouteObserver(tabKeyLogger, context)],
    );
  }
}

基本我的

RouteObserver


class RouteObserver extends NavigatorObserver {
  final String tabKey;
  final BuildContext context;

  RouteObserver(this.tabKey, this.context);

  @override
  void didPush(Route route, Route? previousRoute) {
    super.didPush(route, previousRoute);
    log('[TAB-NAVIGATOR] [$tabKey] [PUSH] ${route.settings.name}');
    if (route.settings.name!.startsWith('drawer')) {
      context.read<HomeBloc>().add(const OnHideBottomNavigatorHomeEvent());
    }
  }

  @override
  void didPop(Route route, Route? previousRoute) {
    super.didPop(route, previousRoute);
    log('[TAB-NAVIGATOR] [$tabKey] [POP] ${route.settings.name}');
    if (route.settings.name!.startsWith('drawer')) {
      context.read<HomeBloc>().add(const OnShowBottomNavigatorHomeEvent());
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.