BottomNavigationBar即底部导航栏控件。显示在应用底部的质感设计控件,用于在少量视图中切换。底部导航栏包含多个以标签、图标或两者搭配的形式显示在项目底部的项目,提供了应用程序的顶级视图之间的快速导航。对于较大的屏幕,侧面导航可能更好。

创建navigation_icon_view.dart文件,定义一个NavigationIconView类,用于管理BottomNavigationBarItem(底部导航栏项目)控件的样式、行为与动画。

import'package:flutter/material.dart';

//创建类,导航图标视图

classNavigationIconView{

//导航图标视图的构造函数

NavigationIconView({

//控件参数,传递图标

Widgeticon,

//控件参数,传递标题

Widgettitle,

//控件参数,传递颜色

Colorcolor,

/*

*Ticker提供者

*由类实现的接口,可以提供Ticker对象

*Ticker对象:每个动画帧调用它的回调一次

*/

TickerProvidervsync,

}):_icon=icon,//接收传递的图标

//接收传递的颜色

_color=color,

//创建底部导航栏项目

item=newBottomNavigationBarItem(

//项目的图标

icon:icon,

//项目的标题

title:title

),

//创建动画控制器

controller=newAnimationController(

//动画持续的时间长度:默认情况下主题更改动画的持续时间

duration:kThemeAnimationDuration,

//垂直同步

vsync:vsync,

){

//创建曲线动画

_animation=newCurvedAnimation(

//应用曲线动画的动画

parent:controller,

/*

*正向使用的曲线:

*从0.5

*到1.0结束

*应用的曲线:快速启动并缓和到最终位置的曲线

*/

curve:newInterval(0.5,1.0,curve:Curves.fastOutSlowIn),

);

}

//类成员,存储图标

finalWidget_icon;

//类成员,存储颜色

finalColor_color;

//类成员,底部导航栏项目

finalBottomNavigationBarItemitem;

//类成员,动画控制器

finalAnimationControllercontroller;

//类成员,曲线动画

CurvedAnimation_animation;

/*

*类函数,过渡转换

*BottomNavigationBarType:定义底部导航栏的布局和行为

*BuildContext:处理控件树中的控件

*/

FadeTransitiontransition(BottomNavigationBarTypetype,BuildContextcontext){

//局部变量,存储图标颜色

ColoriconColor;

//如果底部导航栏的位置和大小在点击时会变大

if(type==BottomNavigationBarType.shifting){

//存储颜色作为图标颜色

iconColor=_color;

}else{

/*

*保存质感设计主题的颜色和排版值:

*使用ThemeData来配置主题控件

*使用Theme.of获取当前主题

*/

finalThemeDatathemeData=Theme.of(context);

/*

*如果程序整体主题的亮度很高(需要深色文本颜色才能实现可读的对比度)

*就返回程序主要部分的背景颜色作为图标颜色

*否则返回控件的前景颜色作为图标颜色

*/

iconColor=themeData.brightness==Brightness.light

?themeData.primaryColor

:themeData.accentColor;

}

//返回值,创建不透明度转换

returnnewFadeTransition(

//控制子控件不透明度的动画

opacity:_animation,

//子控件:创建滑动转换过渡

child:newSlideTransition(

/*

*控制子控件位置的动画

*开始值和结束值之间的线性插值

*(1.0,0.0)表示Size的右上角

*(0.0,1.0)表示Size的左下角

*/

position:newTween(

//此变量在动画开头的值

begin:constFractionalOffset(0.0,0.02),

//此变量在动画结尾处的值:左上角

end:FractionalOffset.topLeft,

).animate(_animation),//返回给定动画,该动画接受由此对象确定的值

//子控件:创建控制子控件的颜色,不透明度和大小的图标主题

child:newIconTheme(

//用于子控件中图标的颜色,不透明度和大小

data:newIconThemeData(

//图标的默认颜色

color:iconColor,

//图标的默认大小

size:120.0,

),

//子控件

child:_icon,

)

)

);

}

}

再创建main.dart文件。类CustomIcon创建一个容器控件,作为一个自定义的图标使用。同时使用质感设计的弹出菜单控件切换底部导航栏的行为和样式。

import'package:flutter/material.dart';

import'navigation_icon_view.dart';

//创建类,自定义图标,继承StatelessWidget(无状态的控件)

classCustomIconextendsStatelessWidget{

//覆盖此函数以构建依赖于动画的当前状态的控件

@override

Widgetbuild(BuildContextcontext){

//获取当前图标主题,创建与此图标主题相同的图标主题

finalIconThemeDataiconTheme=IconTheme.of(context).fallback();

//返回值,创建一个容器控件

returnnewContainer(

//围绕子控件的填充:每个边都偏移4.0

margin:constEdgeInsets.all(4.0),

//容器宽度:图标主题的宽度减8.0

width:iconTheme.size-8.0,

//容器高度:图标主题的高度减8.0

height:iconTheme.size-8.0,

//子控件的装饰:创建一个装饰

decoration:newBoxDecoration(

//背景颜色:图标主题的颜色

backgroundColor:iconTheme.color

)

);

}

}

//创建类,菜单演示,继承StatefulWidget(有状态的控件)

classMenusDemoextendsStatefulWidget{

/*

*覆盖具有相同名称的超类成员

*createState方法在树中的给定位置为此控件创建可变状态

*子类应重写此方法以返回其关联的State子类新创建的实例

*/

@override

_MenusDemoStatecreateState()=>new_MenusDemoState();

}

/*

*关联State子类的实例

*继承State:StatefulWidget(有状态的控件)逻辑和内部状态

*继承TickerProviderStateMixin,提供Ticker对象

*/

class_MenusDemoStateextendsStatewithTickerProviderStateMixin{

//类成员,存储底部导航栏的当前选择

int_currentIndex=2;

//类成员,存储底部导航栏的布局和行为:在点击时会变大

BottomNavigationBarType_type=BottomNavigationBarType.shifting;

//类成员,存储NavigationIconView类的列表

List_navigationViews;

/*

*在对象插入到树中时调用

*框架将为它创建的每个State(状态)对象调用此方法一次

*覆盖此方法可以实现此对象被插入到树中的位置的初始化

*或用于配置此对象上的控件的位置的初始化

*/

@override

voidinitState(){

//调用父类的内容

super.initState();

//在存储NavigationIconView类的列表里添加内容

_navigationViews=[

/*

*创建NavigationIconView类的实例

*传递图标参数

*传递标题参数

*传递颜色参数

*传递Ticker对象

*/

newNavigationIconView(

icon:newIcon(Icons.access_alarm),

title:newText('成就'),

color:Colors.deepPurple[500],

vsync:this,

),

newNavigationIconView(

icon:newCustomIcon(),

title:newText('行动'),

color:Colors.deepOrange[500],

vsync:this,

),

newNavigationIconView(

icon:newIcon(Icons.cloud),

title:newText('人物'),

color:Colors.teal[500],

vsync:this,

),

newNavigationIconView(

icon:newIcon(Icons.favorite),

title:newText('财产'),

color:Colors.indigo[500],

vsync:this,

),

newNavigationIconView(

icon:newIcon(Icons.event_available),

title:newText('设置'),

color:Colors.pink[500],

vsync:this,

),

];

//循环调用存储NavigationIconView类的列表的值

for(NavigationIconViewviewin_navigationViews)

//每次动画控制器的值更改时调用侦听器

view.controller.addListener(_rebuild);

//底部导航栏当前选择的动画控制器的值为1.0

_navigationViews[_currentIndex].controller.value=1.0;

}

//释放此对象使用的资源

@override

voiddispose(){

//调用父类的内容

super.dispose();

//循环调用存储NavigationIconView类的列表中的项

for(NavigationIconViewviewin_navigationViews)

//调用此方法后,对象不再可用

view.controller.dispose();

}

//动画控制器的值更改时的操作

void_rebuild(){

//通知框架此对象的内部状态已更改

setState((){

//重建,以便为视图创建动画

});

}

//建立过渡堆栈

Widget_buildTransitionsStack(){

//局部变量,存储不透明度转换的列表

finalListtransitions=[];

//循环调用存储NavigationIconView类的列表的值

for(NavigationIconViewviewin_navigationViews)

//在存储不透明度转换的列表中添加transition函数的返回值

transitions.add(view.transition(_type,context));

//对存储不透明度转换的列表进行排序

transitions.sort((FadeTransitiona,FadeTransitionb){

finalAnimationaAnimation=a.listenable;

finalAnimationbAnimation=b.listenable;

//aValue:a的动画值

doubleaValue=aAnimation.value;

//bValue:b的动画值

doublebValue=bAnimation.value;

/*

*将aValue与bValue进行比较

*返回一个负整数,aValue排序在bValue之前

*返回一个正整数,aValue排序在bValue之后

*/

returnaValue.compareTo(bValue);

});

//返回值,创建层叠布局控件

returnnewStack(children:transitions);

}

//覆盖此函数以构建依赖于动画的当前状态的控件

@override

Widgetbuild(BuildContextcontext){

//局部变量,创建底部导航栏

finalBottomNavigationBarbotNavBar=newBottomNavigationBar(

/*

*在底部导航栏中布置的交互项:迭代存储NavigationIconView类的列表

*返回此迭代的每个元素的底部导航栏项目

*创建包含此迭代的元素的列表

*/

items:_navigationViews

.map((NavigationIconViewnavigationView)=>navigationView.item)

.toList(),

//当前活动项的索引:存储底部导航栏的当前选择

currentIndex:_currentIndex,

//底部导航栏的布局和行为:存储底部导航栏的布局和行为

type:_type,

//当点击项目时调用的回调

onTap:(intindex){

//通知框架此对象的内部状态已更改

setState((){

//当前选择的底部导航栏项目,开始反向运行此动画

_navigationViews[_currentIndex].controller.reverse();

//更新存储底部导航栏的当前选择

_currentIndex=index;

//当前选择的底部导航栏项目,开始向前运行此动画

_navigationViews[_currentIndex].controller.forward();

});

}

);

//实现基本的质感设计视觉布局结构

returnnewScaffold(

//质感设计应用栏

appBar:newAppBar(

//应用栏中显示的主要控件,包含程序当前内容描述的文本

title:newText('底部导航演示'),

//在标题控件后显示的控件

actions:[

//创建一个显示弹出式菜单的按钮

newPopupMenuButton(

//当用户从此按钮创建的弹出菜单中选择一个值时调用

onSelected:(BottomNavigationBarTypevalue){

//通知框架此对象的内部状态已更改

setState((){

//存储底部导航栏的布局和行为:选择值

_type=value;

});

},

//点击弹出菜单中显示的项目时调用

itemBuilder:(BuildContextcontext)=>>[

/*

*弹出菜单中的显示项目

*返回值:底部导航栏的布局和行为

*子控件:文本控件

*/

newPopupMenuItem(

value:BottomNavigationBarType.fixed,

child:newText('Fixed')

),

newPopupMenuItem(

value:BottomNavigationBarType.shifting,

child:newText('Shifting')

)

]

)

]

),

//主要内容

body:newCenter(

//主要内容:_buildTransitionsStack函数的返回值

child:_buildTransitionsStack()

),

//水平的按钮数组,沿着程序的底部显示

bottomNavigationBar:botNavBar,

);

}

}

//程序入口

voidmain(){

//创建质感设计程序,并放置到主屏幕

runApp(newMaterialApp(

//在窗口管理器中使用此应用程序的单行描述

title:'Flutter教程',

//程序的默认路由的控件

home:newMenusDemo(),

));

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持扣丁学堂。

质感设计 android,扣丁学堂Android开发Flutter质感设计之底部导航相关推荐

  1. python如何离线安装第三方模块_扣丁学堂python开发之第三方模块pip离线安装

    扣丁学堂python开发之第三方模块pip离线安装 2018-08-14 14:02:22 747浏览 最近很多参加Python培训的同学说在学习过程中需要安装一些第三方的模块,今天小编就来给大家讲一 ...

  2. python socket编程之双方相互通信简单实例_扣丁学堂Python开发socket实现简单通信功能实例...

    扣丁学堂Python开发socket实现简单通信功能实例 2018-08-21 14:12:38 747浏览 今天扣丁学堂Python培训老师给大家结合实例介绍一下关于socket实现的简单通信功能, ...

  3. python 匿名函数示例_扣丁学堂Python3开发之匿名函数用法示例详解

    扣丁学堂Python3开发之匿名函数用法示例详解 2018-07-26 14:01:11 1324浏览 今天扣丁学堂Python培训给大家分享关于Python3匿名函数用法,结合实例形式分析了Pyth ...

  4. python 调用event handler_扣丁学堂Python开发之调用语音模块时报错及解决方法

    扣丁学堂Python开发之调用语音模块时报错及解决方法 2018-03-09 11:45:57 3346浏览 python调用语音模块时,遇见TypeError:NoneTypetakesnoargu ...

  5. python代码优化指南_扣丁学堂Python视频教程之Pandas初学者代码优化指南

    扣丁学堂Python视频教程之Pandas初学者代码优化指南 2018-02-05 10:44:24 1320浏览 今天扣丁学堂给大家介绍一下关于Python视频教程之Pandas详解,首先Panda ...

  6. python的excell库_扣丁学堂Python基础教程之Excel处理库openpyxl详解

    扣丁学堂Python基础教程之Excel处理库openpyxl详解 2018-05-04 09:49:49 3197浏览 openpyxl是一个第三方库,可以处理xlsx格式的Excel文件.pipi ...

  7. 千锋扣丁学堂 如何学习android高级编程

    如何学习android高级编程 学了android高级编程有前途吗?进入2010年之后,android的应用开发进入了一个爆炸式增长的状态,从去年的不到1万款应用程序增加到现在的9万,而且即将突破10 ...

  8. python 技巧视频教程_扣丁学堂Python视频教程之Python开发技巧

    扣丁学堂Python视频教程之Python开发技巧 2018-07-25 14:09:44 808浏览 关于Python开发的技巧小编在上篇文章已经给大家分享过一些,本篇文章扣丁学堂 神秘eval: ...

  9. java开发高端说法_扣丁学堂教你如何成为JavaEE高端开发人才

    俗话说干一行爱一行,行行出状元.这句话在如今飞速发展的互联网时代依然实用,如今不少参加学习技术的小伙伴都希望自己可以成为专业的高端开发人才,本篇文章扣丁学堂教你如何成为高端开发人才. 互联网时代,对人 ...

最新文章

  1. 1112-博客十大评论
  2. bzoj2194: 快速傅立叶之二
  3. 什么是死锁,产生的原因,防止死锁的办法
  4. 禁止 VMware Fusion 自动调整 Windows 分辨率
  5. nginx 修改配置文件使之支持pathinfo,且隐藏index.php
  6. 经典排序算法(4)——折半插入排序算法详解
  7. chrome html5 mp4,HTML5 Video Chrome - ffmpeg - mp4 working in all but Chrome
  8. P3-weixin 微信插件式开发规范
  9. vue使用slot分发内容与react使用prop分发内容
  10. ySQL性能优化的21个最佳实践 和 mysql使用索引
  11. 四个措施打造安全的DevOps流程
  12. 全栈JavaScript之路(十三)了解 ElementTraversal 规范
  13. GridView控件 Reapter控件 DataList控件 的区别和用法
  14. 【SpringBoot】24、SpringBoot中实现数据字典
  15. .NET Framework 4.6.1包和语言包下载
  16. 获取打印机分辨率_为孩子准备的第一台口袋打印机,喵喵机P2S评测
  17. .net mqtt 消息收发
  18. java8 List操作
  19. 安卓View — View (一)
  20. Docker学习1-基本命令

热门文章

  1. RS485中继器电路(转)
  2. 航电ACM [hdu 2036] 改革春风吹满地
  3. Android 设置应用程序名称和图标
  4. AT89C51单片机简介
  5. 了解图像分割的深度学习技术(2019年语义分割论文综述)
  6. Android开发-自定义View-AndroidStudio(二十五)数独(2)Handler延迟
  7. deep Learning 之入门一 (ps:知乎上看到的大佬写的非常好,所以自己记录下)
  8. c语言输出一个n行m列的图形
  9. html - 表头固定在顶部的一种实现思路
  10. python 输入一个月份判断季节