笔录Flutter (八)BottomNavigationBar实现底部导航、TabBar+TabBarView实现Tab切换

Flutter练习demo

效果图:
在这里插入图片描述

BottomNavigationBar实现底部导航

在这里插入图片描述

常用属性

在这里插入图片描述

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TabBootomNvPage(),
    );
  }
}



import 'package:flutter/material.dart';

import 'HomeTabPage.dart';
import 'MeTabPage.dart';
import 'SetTabPage.dart';
import 'VideoTabPage.dart';

class TabBootomNvPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return BootomNvPage();
  }
}

class BootomNvPage extends State {

  List _mList = [
    HomeTabPage(),
    MeTabPage(),
    SetTabPage(),
    VideoTabPage(),
  ];

  List _titleList = ["首页", "我的","设置","视屏"];

  List _mIcons = [
    Icon(Icons.home),
    Icon(Icons.mail),
    Icon(Icons.settings),
    Icon(Icons.video_call),
  ];

  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("BottomNv")),
      body: this._mList[this._currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        selectedItemColor:Colors.deepPurple ,// item 选中时的颜色   不设置selectedIconTheme属性  就默认跟字体一个颜色
        unselectedItemColor: Colors.black,// item 未选中时的颜色   不设置unselectedIconTheme属性  就默认跟字体一个颜色

        selectedFontSize: 14, // 选中时字体大小
        unselectedFontSize: 14,// 未选中时字体大小

        iconSize: 30,// item图标大小

        selectedLabelStyle: TextStyle(fontStyle: FontStyle.italic), // 选中时字体style
        unselectedLabelStyle: TextStyle(fontStyle: FontStyle.italic), // 未选中时字体style

        unselectedIconTheme:IconThemeData(color: Colors.amber) ,//设置未选中时icon的颜色
        selectedIconTheme:IconThemeData(color: Colors.green) ,//设置选中时icon的颜色

//        showSelectedLabels: false, // 选中时不显示BottomNavigationBarItem的title
//        showUnselectedLabels: false,//未选中时不显示BottomNavigationBarItem的title

        type: BottomNavigationBarType.fixed,
        currentIndex: this._currentIndex,
        onTap: (index) {
          setState(() {
            this._currentIndex = index;
          });
        },
        items: [_getBottomNv(0),_getBottomNv(1),_getBottomNv(2),_getBottomNv(3)],
      ),
    );
  }

  /**
   * 获取Tab的
   * */
  BottomNavigationBarItem _getBottomNv(int index) {
    return new BottomNavigationBarItem(
      backgroundColor: Colors.amber,
      title: Text(_titleList[index]),
      icon: _mIcons[index],
    );
  }
}


扩展

真实项目中,肯定都会设计自己的底部导航的icon的,看如何实现:
两种实现方式:

1. 第一种(不推荐)
items: [
        _getBottomNv(0),
        _getBottomNv(1),
        _getBottomNv(2),
      ],
/**
   * 获取Tab的item
   * */
  BottomNavigationBarItem _getBottomNv(int index) {
    return new BottomNavigationBarItem(
      backgroundColor: Colors.amber,
      title: Text(_titleList[index]),
      icon: IconButton(
          icon: Container(
         
            width: 20,
            height: 20,
            //三元表达式
            child: currentIndex == 0
                ? Image.asset("images/home_select.png",
                : Image.asset("images/home_unselect.png"),
          ),
          onPressed: null),
    );
  }

这里只有了一个做展示,需要区分 index,去做处理,

注意:

  1. 这样有一个问题就是icon和title之间的距离无法控制
  2. 要想改动icon的大小需要使用Container包裹,借助Container的width、height才可以修改
  3. BottomNavigationBar的iconsize属性将失效
2. 借助BottomNavigationBarItem的activeIcon 属性

我使用的Flutter版是flutter_macos_v1.7.8+hotfix.4-stable .

效果:
在这里插入图片描述
BottomNavigationBarItem提供的又一个activeIcon属性
在这里插入图片描述
activeIcon的源码注释意思就是:选中状态下的图标展示

使用activeIcon必须和icon一起使用

BottomNavigationBarItem _getBottomNv_1(int index) {
    return new BottomNavigationBarItem(
        backgroundColor: Colors.amber,
        title: Text(_titleList[index]),
        icon: _getIcon(index),
        activeIcon: _getActiveIcon(index));
  }

  Widget _getIcon(int index) {
    var image;

    switch (index) {
      case 0:
        image = new Image.asset(
          "images/home_unselect.png",
          width: 25,
          height: 25,
        );
        break;
      case 1:
        image = new Image.asset(
          "images/tax_unselect.png",
          width: 25,
          height: 25,
        );
        break;
      case 2:
        image = new Image.asset(
          "images/me_tab_unselect.png",
          width: 25,
          height: 25,
        );
        break;
    }
    return image;
  }

  Widget _getActiveIcon(int index) {
    var image;

    switch (index) {
      case 0:
        image = new Image.asset(
          "images/home_select.png",
          width: 25,
          height: 25,
        );
        break;
      case 1:
        image = new Image.asset(
          "images/tax_select.png",
          width: 25,
          height: 25,
        );
        break;
      case 2:
        image = new Image.asset(
          "images/me_tab_select.png",
          width: 25,
          height: 25,
        );
        break;
    }
    return image;
  }

注:BottomNavigationBar的iconsize属性将失效

TabBar+TabBarView实现Tab切换

AppBar属性

只简单介绍下本文用到的AppBar的属性

AppBar({
    this.leading,//可以在标题前面显示的一个控件
    this.title,// 一般显示一个text,也可显示其他的组件,title需要返回的是一个widget
    this.bottom,//一个 AppBarBottomWidget 对象,通常是 TabBar。用来在 Toolbar 标题下面显示一个 Tab 导航栏。
  }) 
TabBar属性

源码:

 const TabBar({
    Key key,
    @required this.tabs,
    this.controller,
    this.isScrollable = false,//支持滚动展示
    this.indicatorColor,指示器颜色
    this.indicatorWeight = 2.0,// 指示器的高度
    this.indicatorPadding = EdgeInsets.zero,//指示器距离底部的距离  默认时0
    this.indicator,
    this.indicatorSize,//设置 indicator的长度等于tab标题的长度
    this.labelColor,// 选中时Tab 字体颜色
    this.unselectedLabelColor,// 未选中时Tab 字体颜
    this.labelStyle,// 选中时Tab字体Style
    this.unselectedLabelStyle,// 未选中时Tab字体Style
    this.labelPadding,
    this.dragStartBehavior = DragStartBehavior.start,
    this.onTap,
  }) 
使用
import 'package:flutter/material.dart';

class HomeTabPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return HomeContent();
  }
}

class HomeContent extends State {
  List _tabList = [
    "Flutter",
    "Android",
    "Java",
    "Python",
    "C++",
  ];

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return DefaultTabController(
      length: _tabList.length,
      child: Scaffold(
        appBar: AppBar(
          leading: Icon(Icons.title),
            //bottom: TabBar(。。) 这里用bottom也行,但是顶部会空出来appbar的title部分
          title: TabBar(
            isScrollable: true,
            labelColor: Colors.deepPurple,// 选中时Tab 字体颜色
            unselectedLabelColor: Colors.white,// 未选中时Tab 字体颜
            indicatorWeight: 1.5,// 指示器的高度
            indicatorPadding: EdgeInsets.only(bottom:6), //指示器距离底部的距离  默认时0

            labelStyle: TextStyle(// 选中时Tab字体大小
              fontSize: 18.0,
            ),
            unselectedLabelStyle: TextStyle(
              fontSize: 15.0,
            ),
            indicatorColor: Colors.deepPurple,//指示器颜色
            indicatorSize: TabBarIndicatorSize.label,//设置 indicator的长度等于tab标题的长度

            tabs: [
              _getTabTitle(0),
              _getTabTitle(1),
              _getTabTitle(2),
              _getTabTitle(3),
              _getTabTitle(4),
            ],
          ),
        ),
        body: TabBarView(children: [
          _getTabContent(0),
          _getTabContent(1),
          _getTabContent(2),
          _getTabContent(3),
          _getTabContent(4),
        ]),
      ),
    );
  }

  Widget _getTabTitle(int index) {
    return Tab(
      text: this._tabList[index],
    );
  }

  Widget _getTabContent(int index) {
    return Center(
      child: Text(this._tabList[index]),
    );
  }
}

最后整体的效果:
在这里插入图片描述

具体更多的内容扩展可以自行尝试!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值