颤振:使用导航器推送到新屏幕时保持BottomNavigationBar

kca*_*ack 8 navigator flutter bottomnavigationview

在iOS中,当我们推送到新的ViewController时,我们有一个UITabBarController永久保留在屏幕的底部.

在Flutter中,我们有一个底部导航栏的脚手架.但是,与iOS不同的是,当我们Navigator.push进入新的屏幕时,这个bottomNavigationBar消失了.

在我的应用程序,我想满足这一要求:主屏幕上有一个bottomNavigationBar与2项(&b)提示画面&.默认情况下,屏幕上一个显示.在屏幕A内,有一个按钮.点击该按钮, Navigator.push筛选Ç.现在在屏幕C中,我们仍然可以看到bottomNavigationBar.轻按项目b,我去筛选.现在,在屏幕,龙头项目bottomNavigationBar,我回去屏幕Ç(不是一个,一个是目前低于Ç在导航层次).

我怎样才能做到这一点?多谢你们.

编辑:我包括一些图片用于演示:

屏幕A 屏幕A.

点击转到C按钮,按到屏幕C 屏幕C

点击底部导航栏内的右侧项目,转到屏幕B 屏幕B.

Cop*_*oad 11

截屏:

在此处输入图片说明


初始点:

void main() => runApp(MaterialApp(home: HomePage()));
Run Code Online (Sandbox Code Playgroud)

HomePage[ BottomNavigationBar+ Page1]

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        backgroundColor: Colors.orange,
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.call), label: 'Call'),
          BottomNavigationBarItem(icon: Icon(Icons.message), label: 'Message'),
        ],
      ),
      body: Navigator(
        onGenerateRoute: (settings) {
          Widget page = Page1();
          if (settings.name == 'page2') page = Page2();
          return MaterialPageRoute(builder: (_) => page);
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

第 1 页:

class Page1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page1')),
      body: Center(
        child: RaisedButton(
          onPressed: () => Navigator.pushNamed(context, 'page2'),
          child: Text('Go to Page2'),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

第二页:

class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) => Scaffold(appBar: AppBar(title: Text('Page2')));
}
Run Code Online (Sandbox Code Playgroud)

  • 奇迹般有效。多谢 (3认同)
  • 如何在没有底部导航栏的情况下导航某些屏幕,您能解释一下吗? (3认同)
  • @KunYuTsai 将 `onChanged` 属性添加到 `BottomNavigationBar` 小部件,使用索引来跟踪当前页面,然后使用 `if-else` 条件,例如,选择要显示的小部件。 (3认同)
  • 您可以使用根导航器:`Navigator.of(context, rootNavigator: true).pushFunction(...)`,但您还需要在根中配置路由,例如在materialApp中设置`routes`属性 (2认同)

kca*_*ack 9

tl; dr:使用CupertinoTabBarCupertinoTabScaffold

问题不在于Flutter,而在于用户体验,就像RémiRousselet所提到的那样.

事实证明,Material Design不建议层次结构中的子页面访问底部导航栏.

但是,iOS人机界面指南推荐这一点.因此,要使用此功能,我必须使用Cupertino小部件而不是Material小部件.具体来说,在main中,返回WidgetsApp/MaterialApp包含a的内容CupertinoTabScaffold.用a实现标签栏,CupertinoTabBar每个屏幕都是一个CupertinoTabView.


rob*_*ter 7

您需要使用路线创建MaterialApp,并将BottomNavigationBar设为它的同级。然后使用您传递给BottomNavigationBar的MaterialApp.navigatorKey进行导航。

https://medium.com/@swav.kulinski/flutter-navigating-off-the-charts-e118562a36a5


par*_*ras 7

如果有人想保留底部导航栏,只需从主页正文返回一个导航器并为每个路线传递一个唯一的键即可。

import 'package:bottomnavigation_sample/page1.dart';
import 'package:bottomnavigation_sample/page2.dart';
import 'package:bottomnavigation_sample/page3.dart';
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;
  Map<int, GlobalKey<NavigatorState>> navigatorKeys = {
     0: GlobalKey<NavigatorState>(),
     1: GlobalKey<NavigatorState>(),
     2: GlobalKey<NavigatorState>(),
  };
    final List<Widget> _widgetOptions = <Widget>[
    const page1(),
    const page2(),
    const page3()
  ];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
       bottomNavigationBar: BottomNavigationBar(
         items: const <BottomNavigationBarItem>[
           BottomNavigationBarItem(
             icon: Icon(Icons.home),
             label: 'Home',
           ),
           BottomNavigationBarItem(
             icon: Icon(Icons.business),
             label: 'Business',
           ),
           BottomNavigationBarItem(
             icon: Icon(Icons.school),
             label: 'School',
           ),
         ],
         currentIndex: _selectedIndex,
         selectedItemColor: Colors.amber[800],
         onTap: _onItemTapped,
       ),
      body:  buildNavigator(),
    );
  }

   buildNavigator() {
     return Navigator(
       key: navigatorKeys[_selectedIndex],
       onGenerateRoute: (RouteSettings settings){
         return MaterialPageRoute(builder: (_) => _widgetOptions.elementAt(_selectedIndex));
       },
     );
  }
}
Run Code Online (Sandbox Code Playgroud)