如何在Navigator中使用BottomNavigationBar?

时间:2017-07-21 10:40:53

标签: flutter

BottomNavigationBar的Flutter Gallery示例在Stack的正文中使用了FadeTransitions Scaffold

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

有这方面的例子吗?

6 个答案:

答案 0 :(得分:36)

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

答案 1 :(得分:9)

完整示例

首先创建一个课程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")),
    );
  }
}

enter image description here

答案 2 :(得分:2)

以下是示例:

  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

答案 3 :(得分:1)

这里是一个示例,说明如何将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"))));
    }
  }
}

答案 4 :(得分:0)

输出:

enter image description here

代码:

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")),
      ],
    ),
  );
}

答案 5 :(得分:-1)

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

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

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