繁体   English   中英

如何将 BottomNavigationBar 与 Navigator 一起使用?

[英]How to use BottomNavigationBar with Navigator?

BottomNavigationBar 的FadeTransitions Gallery 示例在Scaffold的主体中使用了BottomNavigationBar Stack

我觉得如果我们可以使用Navigator来切换页面会更干净(也更容易制作动画)。

有这方面的例子吗?

int index = 0;

@override
Widget build(BuildContext context) {
  return new Scaffold(
    body: new Stack(
      children: <Widget>[
        new Offstage(
          offstage: index != 0,
          child: new TickerMode(
            enabled: index == 0,
            child: new MaterialApp(home: new YourLeftPage()),
          ),
        ),
        new Offstage(
          offstage: index != 1,
          child: new TickerMode(
            enabled: index == 1,
            child: new MaterialApp(home: new YourRightPage()),
          ),
        ),
      ],
    ),
    bottomNavigationBar: new BottomNavigationBar(
      currentIndex: index,
      onTap: (int index) { setState((){ this.index = index; }); },
      items: <BottomNavigationBarItem>[
        new BottomNavigationBarItem(
          icon: new Icon(Icons.home),
          title: new Text("Left"),
        ),
        new BottomNavigationBarItem(
          icon: new Icon(Icons.search),
          title: new Text("Right"),
        ),
      ],
    ),
  );
}

您应该通过Stack保留每个页面以保持其状态。 Offstage停止绘画, TickerMode停止动画。 MaterialApp包括Navigator

输出:

在此处输入图片说明

代码:

int _index = 0;

@override
Widget build(BuildContext context) {
  Widget child;
  switch (_index) {
    case 0:
      child = FlutterLogo();
      break;
    case 1:
      child = FlutterLogo(colors: Colors.orange);
      break;
    case 2:
      child = FlutterLogo(colors: Colors.red);
      break;
  }

  return Scaffold(
    body: SizedBox.expand(child: child),
    bottomNavigationBar: BottomNavigationBar(
      onTap: (newIndex) => setState(() => _index = newIndex),
      currentIndex: _index,
      items: [
        BottomNavigationBarItem(icon: Icon(Icons.looks_one), title: Text("Blue")),
        BottomNavigationBarItem(icon: Icon(Icons.looks_two), title: Text("Orange")),
        BottomNavigationBarItem(icon: Icon(Icons.looks_3), title: Text("Red")),
      ],
    ),
  );
}

完整示例

首先创建一个类MyBottomBarDemo

class MyBottomBarDemo extends StatefulWidget {
  @override
  _MyBottomBarDemoState createState() => new _MyBottomBarDemoState();
}

class _MyBottomBarDemoState extends State<MyBottomBarDemo> {
  int _pageIndex = 0;
  PageController _pageController;

  List<Widget> tabPages = [
    Screen1(),
    Screen2(),
    Screen3(),
  ];

  @override
  void initState(){
    super.initState();
    _pageController = PageController(initialPage: _pageIndex);
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BottomNavigationBar", style: TextStyle(color: Colors.white)),
        backgroundColor: Colors.deepPurple,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _pageIndex,
        onTap: onTabTapped,
        backgroundColor: Colors.white,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem( icon: Icon(Icons.home), title: Text("Home")),
          BottomNavigationBarItem(icon: Icon(Icons.mail), title: Text("Messages")),
          BottomNavigationBarItem(icon: Icon(Icons.person), title: Text("Profile")),
        ],

      ),
      body: PageView(
        children: tabPages,
        onPageChanged: onPageChanged,
        controller: _pageController,
      ),
    );
  }
  void onPageChanged(int page) {
    setState(() {
      this._pageIndex = page;
    });
  }

  void onTabTapped(int index) {
    this._pageController.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
  }
}

然后创建一个你的屏幕

class Screen1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        color: Colors.green,
            child: Center(child: Text("Screen 1")),
    );
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      child: Center(child: Text("Screen 2")),
    );
  }
}

class Screen3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.cyan,
      child: Center(child: Text("Screen 3")),
    );
  }
}

在此处输入图片说明

下面是一个如何使用 Navigator 和 BottomNavigationBar 来导航不同屏幕的示例。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

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

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // This navigator state will be used to navigate different pages
  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
  int _currentTabIndex = 0;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Navigator(key: _navigatorKey, onGenerateRoute: generateRoute),
        bottomNavigationBar: _bottomNavigationBar(),
      ),
    );
  }

  Widget _bottomNavigationBar() {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      items: [
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          title: Text("Home"),
        ),
        BottomNavigationBarItem(
            icon: Icon(Icons.account_circle), title: Text("Account")),
        BottomNavigationBarItem(
          icon: Icon(Icons.settings),
          title: Text("Settings"),
        )
      ],
      onTap: _onTap,
      currentIndex: _currentTabIndex,
    );
  }

  _onTap(int tabIndex) {
    switch (tabIndex) {
      case 0:
        _navigatorKey.currentState.pushReplacementNamed("Home");
        break;
      case 1:
        _navigatorKey.currentState.pushReplacementNamed("Account");
        break;
      case 2:
        _navigatorKey.currentState.pushReplacementNamed("Settings");
        break;
    }
    setState(() {
      _currentTabIndex = tabIndex;
    });
  }

  Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case "Account":
        return MaterialPageRoute(builder: (context) => Container(color: Colors.blue,child: Center(child: Text("Account"))));
      case "Settings":
        return MaterialPageRoute(builder: (context) => Container(color: Colors.green,child: Center(child: Text("Settings"))));
      default:
        return MaterialPageRoute(builder: (context) => Container(color: Colors.white,child: Center(child: Text("Home"))));
    }
  }
}

这是示例:

  int _currentIndex = 0;


  Route<Null> _getRoute(RouteSettings settings) {
    final initialSettings = new RouteSettings(
        name: settings.name,
        isInitialRoute: true);

    return new MaterialPageRoute<Null>(
        settings: initialSettings,
        builder: (context) =>
        new Scaffold(
          body: new Center(
              child: new Container(
                  height: 200.0,
                  width: 200.0,
                  child: new Column(children: <Widget>[
                    new Text(settings.name),
                    new FlatButton(onPressed: () =>
                        Navigator.of(context).pushNamed(
                            "${settings.name}/next"), child: new Text("push")),
                  ],
                  ))
          ),
          bottomNavigationBar: new BottomNavigationBar(
              currentIndex: _currentIndex,
              onTap: (value) {
                final routes = ["/list", "/map"];
                _currentIndex = value;
                Navigator.of(context).pushNamedAndRemoveUntil(
                    routes[value], (route) => false);
              },
              items: [
                new BottomNavigationBarItem(
                    icon: new Icon(Icons.list), title: new Text("List")),
                new BottomNavigationBarItem(
                    icon: new Icon(Icons.map), title: new Text("Map")),
              ]),
        ));
  }

  @override
  Widget build(BuildContext context) =>
      new MaterialApp(
        initialRoute: "/list",
        onGenerateRoute: _getRoute,
        theme: new ThemeData(
          primarySwatch: Colors.blue,
        ),
      );

您可以将isInitialRoute设置为 true 并将其传递给 MaterialPageRoute。 它将删除流行动画。

要删除旧路由,您可以使用pushNamedAndRemoveUntil

Navigator.of(context).pushNamedAndRemoveUntil(routes[value], (route) => false);

要设置当前页面,您可以在状态_currentIndex有一个变量并将其分配给BottomNavigationBar

Navigator.of(context).pushNamedAndRemoveUntil(
                routes[value], (route) => true);

我必须使用 true 才能启用后退按钮。

注意:我使用Navigator.pushNamed()进行导航。

这是我在项目中使用的代码。 如果您尝试避免使用页面查看器,那么您可以试试这个

import 'package:flutter/material.dart';

class Dashboard extends StatefulWidget {
  const Dashboard({Key? key}) : super(key: key);

  @override
  State<Dashboard> createState() => _DashboardState();
}

class _DashboardState extends State<Dashboard> {
  int _selectedIndex = 0;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sample'),
      ),
      body: SingleChildScrollView(
       child: Column(
        children: [
          if (_selectedIndex == 0)
            // you can call custom widget here
            Column(
              children: const [
                Text("0"),
              ],
            )
          else if (_selectedIndex == 1)
             Column(
                children: const [
                  Text("1"),
                ],                 
            )
          else             
               Column(
                children: const [
                  Text("2"),
                ],               
            ),
        ],
      ),
     ),

      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.headphones),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            label: 'Business',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            label: 'School',
          ),              
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        unselectedItemColor: Colors.grey,
        onTap: _onItemTapped,
      ),
    );
  }
}

快乐编码

很高兴你问,几个月前我尝试过这个,并试图通过一篇博客文章来简化它。 我将无法在此处发布完整的代码,因为它很长,但我当然可以链接所有资源以澄清它。

  1. flutter中的BottomNavigationBar的一切
  2. 完整的示例代码
  3. 飞镖演示
  4. 如果您愿意,也可以依赖此 package https://pub.dev/packages/navbar_router

这是本文帮助您构建的结果 output

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM