Flutter 底部导航栏bottomNavigationBar

实现一个底部导航栏,包含3到4个功能标签,点击对应的导航标签可以切换到对应的页面内容,并且页面抬头显示的内容也会跟着改变。
实际上由于手机屏幕大小的限制,底部导航栏的功能标签一般在3到5个左右,如果太多,会比较拥挤,影响用户体验,实际上目前市面上大多数APP的底部导航标签都控制在4到5个左右。既美观、又不会让用户觉得功能繁杂。这个功能的实现需要用到flutter里的BottonNavigationBar这个控件。
属性名 类型 说明
currentIndex int 当前索引,用来切换按钮控制
fixedColor Color 选中按钮的颜色,如果没有指定值,则用系统主题色
iconSize double 按钮图标大小
items List<BottomNavigationBarItem> 底部导航条按钮集。每一项是一个BottomNavigationBarItem,有icon图标及title属性
onTap ValueChanged<int> 按下其中某一个按钮回调事件,需要根据返回的索引设置当前索引
首先我们新建一个底部导航控件,由于点击导航标签的时候页面内容是会发生改变的,所以这是一个有状态的控件。
import 'package:flutter/material.dart';
import './home.dart';
import './contacts.dart';
import './me.dart';

// 应用页面使用有状态Widget
class App extends StatefulWidget {
  @override
  AppState createState() => AppState();
}
//应用页面状态实现类
class AppState extends State<App> {
  //当前选中页面索引
  var _currentIndex = 0;
  //聊天页面
  HomePage home;
  //好友页面
  Contacts contacts;
  //我的页面
  Personal me;

  //根据当前索引返回不同的页面
  currentPage(){
    switch(_currentIndex) {
      case 0:
        //返回聊天页面
        if(home == null) {
          home = new HomePage();
        }
        return home;
      case 1:
        //返回好友页面
        if(contacts == null) {
          contacts = new Contacts();
        }
        return contacts;
      case 2:
        //返回我的页面
        if(me == null) {
          me = new Personal();
        }
        return me;
    }
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(

      //底部导航按钮
      bottomNavigationBar: new BottomNavigationBar(
        //通过fixedColor设置选中item的颜色
        fixedColor:Colors.red,
        type: BottomNavigationBarType.fixed,
        //当前页面索引
        currentIndex: _currentIndex,
        //按下后设置当前页面索引
        onTap: ((index){
          setState(() {
            _currentIndex = index;
          });
        }),
        //底部导航按钮项
        items: [
          //导航按钮项传入文本及图标
          new BottomNavigationBarItem(
            title: new Text(
              '聊天',
              style: TextStyle(
                color: _currentIndex == 0 ? Color(0xFFF54343) : Color(0xff999999) //0x 后面开始 两位FF表示透明度16进制 后面是颜色
              ),
            ),
            //判断当然索引做图片切换显示
            icon: _currentIndex == 0 
              ? Image.asset(
                'images/nav-icon-index.active.png',
                width: 32.0,
                height: 32.0,
              ) 
              : Image.asset(
                'images/nav-icon-index.png',
                width: 32.0,
                height: 32.0,
              )
          ),
          new BottomNavigationBarItem(
            title: new Text(
              '好友',
              style: TextStyle(
                color: _currentIndex == 1 ? Color(0xFFF54343) : Color(0xff999999)
              ),
            ),
            //判断当然索引做图片切换显示
            icon: _currentIndex == 1 
              ? Image.asset(
                'images/nav-icon-cat.active.png',
                width: 32.0,
                height: 32.0,
              ) 
              : Image.asset(
                'images/nav-icon-cat.png',
                width: 32.0,
                height: 32.0,
              )
          ),
          new BottomNavigationBarItem(
            title: new Text(
              '我的',
              style: TextStyle(
                color: _currentIndex == 2 ? Color(0xFFF54343) : Color(0xff999999)
              ),
            ),
            //判断当然索引做图片切换显示
            icon: _currentIndex == 2 
              ? Image.asset(
                'images/nav-icon-user.active.png',
                width: 32.0,
                height: 32.0,
              ) 
              : Image.asset(
                'images/nav-icon-user.png',
                width: 32.0,
                height: 32.0,
              )
          ),
        ],
      ),

      //中间显示当前页面
      body: currentPage(),

    );
  }
}
fixedColor设置选中的颜色,下面可以不单独写color。
 

新建三个dart文件,分别用于新建3个主体展示页面,这三个页面都是带一个appbar和body,appbar用于显示对应的导航标签,body里显示标签大图标。三个文件的写法基本是一致的。

import 'package:flutter/material.dart';

class Personal extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return new PersonalState();
  }
}

class PersonalState extends State<Personal>{
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('我的'),
      ),
      body: new Center(
        child: Icon(Icons.mood,size: 130.0,color: Colors.blue,),
      ),
    );
  }
}

 另外一种实现方法,重新initState()方法:

List<Widget> blist = List();
 @override
 void initState(){
    blist
      ..add(HomePage())
      ..add(Contacts())
      ..add(Personal());
    super.initState();
  }

这里的..add()是Dart语言的..语法,如果你学过编程模式,你一定听说过建造者模式,简单来说就是返回调用者本身。这里list后用了..add(),还会返回list,然后就一直使用..语法,能一直想list里增加widget元素。 最后我们调用了一些父类的initState()方法。

完整代码:

import 'package:flutter/material.dart';
import './home.dart';
import './contacts.dart';
import './me.dart';

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp>  {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('底部导航示例')),
      body: BottomNavigationWidget(),
    );
  }
}

class BottomNavigationWidget extends StatefulWidget {

  _BottomNavigationWidgetState createState() => _BottomNavigationWidgetState();
}

class _BottomNavigationWidgetState extends State<BottomNavigationWidget> {
  final _BottomNavigationColor = Colors.red;
  int _currentIndex = 0;
  List<Widget> blist = List();

  @override
  void initState(){
    blist
      ..add(HomePage()) //建造者模式,简单来说就是返回调用者本身。这里blist后用了..add(),还会返回blist
      ..add(Contacts())
      ..add(Personal());
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
       bottomNavigationBar:BottomNavigationBar(
         items: [
           BottomNavigationBarItem(
            icon: Icon(Icons.home,color: _BottomNavigationColor,),
            title:Text('Hmoe',style: TextStyle(color: _BottomNavigationColor),) 
           ),
           BottomNavigationBarItem(
            icon: Icon(Icons.email,color: _BottomNavigationColor,),
            title:Text('Email',style: TextStyle(color: _BottomNavigationColor),) 
           ),
           BottomNavigationBarItem(
            icon: Icon(Icons.pages,color: _BottomNavigationColor,),
            title:Text('Pages',style: TextStyle(color: _BottomNavigationColor),) 
           ),
         ],
         currentIndex: _currentIndex, //当前页面索引,高亮
         onTap: (int index){
           setState(() {
             _currentIndex = index; 
           });
         },
       ) ,
       body: blist[_currentIndex],
    );
  }
}

 

posted on 2019-07-12 16:11  JoeYoung  阅读(2885)  评论(0编辑  收藏  举报