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

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

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

e0078296b7b9fb167ddc54bce8e21c05.png

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(),

));

}

d18c1c8974a48a3e58579f9f7dae87fe.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值