如何从带有底部导航栏的脚手架主体内部推送路线?

How to push a Route from inside the body of a scaffold with a bottomnavigationbar?

我的 main.dart 中的 Nav() 小部件中有一个 MaterialApp,它包含一个带有 appBar 和 BottomNavigationBar 的脚手架。 NavigationBar 有 4 个 BottomNavigationBarItems,但我的整个应用程序中的页面多于 4 个。可以通过第一个 BottomNavigationBarItem 'Home' 访问其他页面。但是当我推送新的 NamedRoute 时,AppBar 消失了。我该如何解决这个问题?

我已经尝试在新文件中使用我自己的 Widget 中的 bottomNavigationBar。问题:setState() 不起作用。

这是一些代码

main.dart:

import 'package:flutter/material.dart';
import 'pages/nav.dart';
import 'route/route.dart' as route;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Lieferantenapp',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.red,
      ),
      home: Nav(),
      onGenerateRoute: route.controller,
      //initialRoute: route.navPage,
    );
  }
}

nav.dart

import 'package:flutter/material.dart';
import 'package:lieferantenapp/components/MyAppBar.dart';
import 'package:lieferantenapp/components/MyThreeLineText.dart';
//import 'package:lieferantenapp/components/myBottomNavigationBar.dart';
import 'package:lieferantenapp/components/myCard.dart';
import 'package:lieferantenapp/pages/bestellungen.dart';
import 'package:lieferantenapp/pages/packliste.dart';
import 'package:lieferantenapp/pages/tour.dart';
import 'package:lieferantenapp/pages/home.dart';

class Nav extends StatefulWidget {
  @override
  _NavState createState() => _NavState();
}

class _NavState extends State<Nav> {
  int _selectedIndex = 0;
  List<Widget> _widgetOptions = <Widget>[
    Home(),
    Tour(),
    Bestellungen(),
    Packliste(),
  ];

  void _onItemTap(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //Custom App Bar without any passed data
      appBar: myAppBar(context, null, null),
      backgroundColor: Colors.white,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        type: BottomNavigationBarType.fixed,
        fixedColor: Colors.red,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
          BottomNavigationBarItem(
            icon: Icon(Icons.local_shipping),
            label: 'Tour',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.inventory_2),
            label: 'Packliste',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.receipt_long),
            label: 'Bestellungen',
          ),
        ],
        onTap: _onItemTap,
      ),
      body: _widgetOptions.elementAt(_selectedIndex),
    );
  }
}

home.dart:

import 'package:flutter/material.dart';
import 'package:lieferantenapp/components/MyThreeLineText.dart';
import 'package:lieferantenapp/components/myCard.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        //BlackBoard Message
        //TODO get BlackBoard Message from Server
        //myThreeLineText(Context, TextTheme, OVerline, Title, Body)
        myThreeLineText(
          context,
          Theme.of(context).textTheme,
          '12.07.2021',
          'Servus und Mahlzeit!',
          "Herzlich Willkommen in der neuen Mahlzeit LieferApp mit " +
              "optimierter Routenplanung via Google Maps.",
        ),
        Expanded(
          child: GridView.count(
            shrinkWrap: true,
            primary: false,
            padding: const EdgeInsets.all(18),
            crossAxisSpacing: 15,
            mainAxisSpacing: 15,
            crossAxisCount: 2,
            children: <Widget>[
              myCard(
                context,
                Icons.map_outlined,
                'Touren',
                Theme.of(context).textTheme,
                Color(0xff119052),
              ),
              myCard(
                context,
                Icons.local_shipping_outlined,
                'Touren',
                Theme.of(context).textTheme,
                Color(0xffFF9444),
              ),
              myCard(
                context,
                Icons.inventory_2_outlined,
                'Touren',
                Theme.of(context).textTheme,
                Color(0xff84000F),
              ),
              myCard(
                context,
                Icons.receipt_long_outlined,
                'Touren',
                Theme.of(context).textTheme,
                Color(0xffCB5E5E),
              ),
              myCard(
                context,
                Icons.bookmark_border_outlined,
                'Touren',
                Theme.of(context).textTheme,
                Color(0xffCC3021),
              ),
              myCard(
                context,
                Icons.settings_outlined,
                'Touren',
                Theme.of(context).textTheme,
                Color(0xff57BB61),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

myCard.dart:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:lieferantenapp/route/route.dart' as route;

Widget myCard(BuildContext context, IconData icon, String text, TextTheme theme,
    Color cColor) {
  return GestureDetector(
    //TODO implement ROUTE ontap start Cards
    onTap: () => {},
    child: Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(30),
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(
            icon,
            color: Colors.white,
            size: 30,
          ),
          SizedBox(height: 25),
          Text(
            text,
            style: theme.bodyText1.apply(color: Colors.white),
          ),
        ],
      ),
      color: cColor,
    ),
  );
}

我也愿意接受提示和技巧来改进我的代码。

编辑 - 新 main.dart:

import 'package:flutter/material.dart';
import 'package:lieferantenapp/components/MyAppBar.dart';

import 'pages/nav.dart';
import 'route/route.dart' as route;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Mahlzeit Lieferantenapp',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      //home: Nav(),
      //onGenerateRoute: route.controller,
      builder: (context, _) => Scaffold(
        appBar: myAppBar(context, null, null),
        body: Navigator(onGenerateRoute: route.controller),
      ),
      //initialRoute: route.navPage,
    );
  }
}

应用栏是脚手架的一部分,它只会出现在 _widgetOptions 中的 4 个小部件上。如果您的页面上没有该脚手架,则没有应用栏。

用脚手架包裹导航器(即导航器顶部的脚手架)应该可以解决问题。

请注意,当您 'returning' 来自构建函数的 Widget 时,它会成为子项。当您使用 Navigator 推送 Widget 时,它会成为同级组件,并且将位于当前屏幕的顶部。您可以在开发工具中清楚地看到这一点。

编辑:因为您使用的是默认的 MaterialApp 导航器,所以这将不起作用。您需要为此创建自己的导航器。

即:从 MaterialApp 中删除 home 参数。请改用构建器参数。并向构建器提供一个 Navigator 小部件(由您的脚手架包裹)

像这样:

MaterialApp(builder: (context, _) => Scaffold( ....., body: Navigator( onGenerateRoutes:...)))