底部导航栏制作 - 图1

主入口文件的编写 main.dart

首先我们先写一个主入口文件,这个文件只是简单的APP通用结构,最主要的是要引入自定义的 BottomNavigationWidget 组件

  1. import 'package:flutter/material.dart';
  2. import 'bottom_navigation_widget.dart';
  3. void main()=> runApp(new MyApp());
  4. class MyApp extends StatelessWidget {
  5. @override
  6. Widget build(BuildContext context) {
  7. return MaterialApp(
  8. title:'Flutter bottomNavigationBar',
  9. theme:ThemeData.light(),
  10. home:BottomNavigationWidget()
  11. );
  12. }.
  13. }

注意的是 BottomNaivgationWidget 这个组件还没有编写,所以现在会报错

子页面的编写

子页面我们就采用最简单的编写了,只放入一个 AppBar 和一个 Center,然后用Text Widget表明即可

在lib目录下新建 pages 目录,然后在目录下面新建文件写子组件,

  1. import 'package:flutter/material.dart';
  2. class HomeScreen extends StatelessWidget {
  3. @override
  4. Widget build(BuildContext context) {
  5. return Scaffold(
  6. appBar:AppBar(
  7. title: Text('HOME'),
  8. ),
  9. body:Center(
  10. child: Text('HOME'),
  11. )
  12. );
  13. }
  14. }

根据有了这个代码进行对应修改,分别建立:

文件名字 组件名称
home_screen.dart HomeScreen
email_screen.dart EmailScreen
pages_screen.dart PagesScreen
airplay_screen.dart AirplayScreen

这些都是导航要用的子页面,有了这些页面,我们才能继续编写代码

bottom_navigation_widget.dart 文件

StatefulWidget 讲解

在编写 BottomNaivgationWidget 组件前,我们需要简单了解一下什么是 StatefulWidget

  • StatefulWidget具有可变状态(state)的窗口组件(widget)
  • 使用这个要根据变化状态,调整State值

它的初始化和以前使用的StatelessWidget不同,直接在VSCode中输入 stful 快捷方式生成代码

  1. class name extends StatefulWidget {
  2. _nameState createState() => _nameState();
  3. }
  4. class _nameState extends State<name> {
  5. @override
  6. Widget build(BuildContext context) {
  7. return Container(
  8. child: child,
  9. );
  10. }
  11. }

上面的代码可以清楚的看到,使用StatefulWidget分为两个部分

  • 第一个部分是继承 StatefullWidget
  • 第二个部分是继承于State,其实State部分才是我们的重点,主要的代码都会写在State中

新建 bottom_navigation_widget.dart 文件

  • 在lib目录下,新建一个 bottom_navigation_widget.dart 文件
  • 接下来我们就要创建 BottomNaivgationWidget 这个Widget了,只是建立一个底部导航
  1. import 'package:flutter/material.dart';
  2. class BottomNavigationWidget extends StatefulWidget {
  3. _BottomNavigationWidgetState createState() => _BottomNavigationWidgetState();
  4. }
  5. class _BottomNavigationWidgetState extends State<BottomNavigationWidget> {
  6. final _BottomNavigationColor = Colors.blue;
  7. @override
  8. Widget build(BuildContext context) {
  9. return Scaffold(
  10. bottomNavigationBar: BottomNavigationBar(
  11. items: [
  12. BottomNavigationBarItem(
  13. icon:Icon(
  14. Icons.home,
  15. color:_BottomNavigationColor,
  16. ),
  17. title:Text(
  18. 'Home',
  19. style:TextStyle(color:_BottomNavigationColor)
  20. )
  21. ),
  22. BottomNavigationBarItem(
  23. icon:Icon(
  24. Icons.email,
  25. color:_BottomNavigationColor,
  26. ),
  27. title:Text(
  28. 'Email',
  29. style:TextStyle(color:_BottomNavigationColor)
  30. )
  31. ),
  32. BottomNavigationBarItem(
  33. icon:Icon(
  34. Icons.pages,
  35. color:_BottomNavigationColor,
  36. ),
  37. title:Text(
  38. 'Pages',
  39. style:TextStyle(color:_BottomNavigationColor)
  40. )
  41. ),
  42. BottomNavigationBarItem(
  43. icon:Icon(
  44. Icons.airplay,
  45. color:_BottomNavigationColor,
  46. ),
  47. title:Text(
  48. 'AipPlay',
  49. style:TextStyle(color:_BottomNavigationColor)
  50. )
  51. ),
  52. ],
  53. type:BottomNavigationBarType.fixed
  54. ),
  55. );
  56. }
  57. }

重写initState()方法

我们要重新 initState() 方法,把刚才做好的页面进行初始化到一个Widget数组中。有了数组就可以根据数组的索引来切换不同的页面了。这是现在几乎所有的APP采用的方式。
代码如下:

  1. List<Widget> list = List();
  2. @override
  3. void initState(){
  4. list
  5. ..add(HomeScreen())
  6. ..add(EmailScreen())
  7. ..add(PagesScreen())
  8. ..add(AirplayScreen());
  9. super.initState();
  10. }

这里的..add()是Dart语言的..语法,简单来说就是返回调用者本身

  • 如果你听说过建造者模式,就很容易理解。这里list后用了..add(),还会返回list
  • 然后就一直使用..语法,能一直想list里增加widget元素
  • 最后我们调用了一些父类的 initState() 方法

BottomNavigationBar里的响应事件

BottomNavigationBar 组件里提供了一个相应事件onTap,这个事件自带一个索引值 index,通过索引值我们就可以和我们list里的索引值相对应了。

  1. onTap:(int index){
  2. setState((){
  3. _currentIndex= index;
  4. });
  5. },

完整bottom_navigation_widget.dart

import 'package:flutter/material.dart';
import 'pages/home_screen.dart';
import 'pages/email_screen.dart';
import 'pages/pages_screen.dart';
import 'pages/airplay_screen.dart';

class BottomNavigationWidget extends StatefulWidget {
  _BottomNavigationWidgetState createState() => _BottomNavigationWidgetState();
}

class _BottomNavigationWidgetState extends State<BottomNavigationWidget> {
  final _bottomNavigationColor = Colors.grey;
  final _bottomClickNavigationColor = Colors.blue;
  int _currentIndex = 0;
  List<Widget> list = List();
  @override
  void initState() {
    list
      ..add(HomeScreen())
      ..add(EmailScreen())
      ..add(PagesScreen())
      ..add(AirplayScreen());
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: list[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
              icon: Icon(
                Icons.home,
                color: _currentIndex == 0
                    ? _bottomClickNavigationColor
                    : _bottomNavigationColor,
              ),
              title: Text('Home',
                  style: TextStyle(
                      color: _currentIndex == 0
                          ? _bottomClickNavigationColor
                          : _bottomNavigationColor))),
          BottomNavigationBarItem(
              icon: Icon(
                Icons.email,
                color: _currentIndex == 1
                    ? _bottomClickNavigationColor
                    : _bottomNavigationColor,
              ),
              title: Text('Email',
                  style: TextStyle(
                      color: _currentIndex == 1
                          ? _bottomClickNavigationColor
                          : _bottomNavigationColor))),
          BottomNavigationBarItem(
              icon: Icon(
                Icons.pages,
                color: _currentIndex == 2
                    ? _bottomClickNavigationColor
                    : _bottomNavigationColor,
              ),
              title: Text('Pages',
                  style: TextStyle(
                      color: _currentIndex == 2
                          ? _bottomClickNavigationColor
                          : _bottomNavigationColor))),
          BottomNavigationBarItem(
              icon: Icon(
                Icons.airplay,
                color: _currentIndex == 3
                    ? _bottomClickNavigationColor
                    : _bottomNavigationColor,
              ),
              title: Text('AipPlay',
                  style: TextStyle(
                      color: _currentIndex == 3
                          ? _bottomClickNavigationColor
                          : _bottomNavigationColor))),
        ],
        currentIndex: _currentIndex,
        //backgroundColor: Color.fromRGBO(244, 245, 245, 1.0),
        //fixedColor: Colors.blue,
        onTap: (int index) {
          setState(() {
            _currentIndex = index;
          });
        },
        type: BottomNavigationBarType.fixed,
      ),
    );
  }
}

附件

底部导航栏制作-lib.zip