flutter 为什么我的顶级脚手架无法检测堆栈上有哪些路由?

qxgroojn  于 2023-06-24  发布在  Flutter
关注(0)|答案(2)|浏览(129)

我从一个在有状态小部件中创建的顶层scaffold开始。应用程序会自动导航到回家路线,并且appbar减去后退按钮会正确显示。
下面是主代码

Widget build(BuildContext context) {
  return MultiProvider(
    providers: [
      ChangeNotifierProvider<MyAquariumManagerModel>(
        create: (_) => MyAquariumManagerModel(manageSession),
      ),
      ChangeNotifierProvider<MyAquariumManagerFacilityModel>(
        create: (_) => MyAquariumManagerFacilityModel(manageSession),
      ),
      ChangeNotifierProvider<MyAquariumManagerTanksModel>(
        create: (_) => MyAquariumManagerTanksModel(manageSession),
      ),
      ChangeNotifierProvider<MyAquariumManagerSearchModel>(
        create: (_) => MyAquariumManagerSearchModel(manageSession),
      ),
    ],
    child: MaterialApp(
      title: kProgramName,
      theme: aquarium_manager_theme,
      home: ScaffoldController(),
    ),
  );
}

和顶级ScaffoldController

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text(kProgramName),
    ),
  body: Navigator(
      initialRoute: '/',
      onGenerateRoute: (RouteSettings settings) {
        WidgetBuilder builder;
        switch (settings.name) {
          case '/':
            builder = (BuildContext _) => MyAquariumManagerLoginController(); <-there is no other scaffold here; it depends on the top-level one (this one right here)
            break;
          case '/homescreen':
            builder = (BuildContext _) => AquariumManagerHomeScreenController(); <- there is also no other scaffold here, we never navigate here. MyAquariumManagerLoginController just returns the widgets of this controller.
            break;
          case '/searchscreen':
            builder = (BuildContext _) => MyAquariumManagerSearchController();
            break;
          case '/facilitiesscreen':
            builder = (BuildContext _) => MyAquariumManagerFacilitiesController();
            break;
          case '/tanksscreen':
            builder = (BuildContext _) => MyAquariumManagerTankController(arguments: {
              'incomingRack_Fk': null,
              'incomingTankPosition': null,
            },);
            break;
          default:
            throw Exception('Invalid route: ${settings.name}');
        }
        return MaterialPageRoute(builder: builder, settings: settings);
      },
    ),
  );
}

我以这种方式导航到其他屏幕

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => MyAquariumManagerFacilitiesController(),
    settings: RouteSettings(name: '/facilitiesscreen'),
  ),
)

顶层的appbar仍然存在,但没有后退按钮。其中一些屏幕恰好有自己的scaffold,它们的appbar出现在顶层scaffold的appbar下面,但是这个appbar确实显示了一个后退按钮。
理想情况下,我希望从各个路径中移除脚手架,只保留顶层脚手架,但如何让它显示自己的后退按钮?
我尝试强制按钮出现,然后弹出路由栈,我总是得到一个黑屏,所以出于某种原因,顶层脚手架不知道路由栈上有什么,但我不知道为什么。对于少数有自己的scaffold的路由,它们的返回按钮可以工作,所以在某些地方,它知道堆栈上有哪些路由。

bqucvtff

bqucvtff1#

BackButton“AppBar,当脚手架没有抽屉并且当前路由不是导航器的第一个路由时,它会自动在AppBar前导插槽中使用BackButton。”
在您的例子中,它实际上是第一条路线,因为您的导航恰好位于主Scaffold的主体中-因此它是嵌套的。如果我没记错的话,内置的BackButton不允许您按照您想要的方式自定义它。相反,您可以构建自定义的后退按钮,并从AppBar禁用默认按钮。
虽然,我个人只会使用来自pub.dev的包,如go_router,这使得使用嵌套路由和整体导航非常方便。

alen0pnh

alen0pnh2#

正确的答案是让导航器路由成为材料应用程序的一部分,并确保每个屏幕都有自己的支架。

Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<MyAquariumManagerModel>(
          create: (_) => MyAquariumManagerModel(manageSession),
        ),
        ChangeNotifierProvider<MyAquariumManagerFacilityModel>(
          create: (_) => MyAquariumManagerFacilityModel(manageSession),
        ),
        ChangeNotifierProvider<MyAquariumManagerTanksModel>(
          create: (_) => MyAquariumManagerTanksModel(manageSession),
        ),
        ChangeNotifierProvider<MyAquariumManagerSearchModel>(
          create: (_) => MyAquariumManagerSearchModel(manageSession),
        ),
      ],
      child: MaterialApp(
        title: kProgramName,
        theme: aquarium_manager_theme,
        home: MyAquariumManagerLoginController(),
        onGenerateRoute: (RouteSettings settings) {
          WidgetBuilder builder;
          switch (settings.name) {
            case '/':
              builder = (BuildContext _) => MyAquariumManagerLoginController();
              break;
            case '/homescreen':
              builder = (BuildContext _) => AquariumManagerHomeScreenController();
              break;
            case '/searchscreen':
              builder = (BuildContext _) => MyAquariumManagerSearchController();
              break;
            case '/facilitiesscreen':
              builder = (BuildContext _) => MyAquariumManagerFacilitiesController();
              break;
            case '/tanksscreen':
              builder = (BuildContext _) => MyAquariumManagerTankController(
                arguments: {
                  'incomingRack_Fk': null,
                  'incomingTankPosition': null,
                },
              );
              break;
            default:
              throw Exception('Invalid route: ${settings.name}');
          }
          return MaterialPageRoute(builder: builder, settings: settings);
        },
      ),
    );
  }

相关问题