【Flutter学习】基本组件之TabBar顶部导航
一,概述
TabBar,是材料设计(Material design)中很常用的一种横向标签页。在Android原生开发中,我们常用ViewPage或者一些常用的标签页开源库,来实现并行界面的横向滑动展示,在iOS原生开发中我们可以基于UICollectionView/UIButton来封装实现这一功能,在Flutter的世界中,TabBar是被定义在Material Component中,所以他的使用需要在MaterialApp中。通常,我们会在AppBar的底部部分结合TabBarView来使用TabBar。

二,Tab关键元素
- TabController
这是Tab页的控制器,用于定义Tab标签和内容页的坐标,还可配置标签页的切换动画效果等。
TabController一般放入有状态控件中使用,以适应标签页数量和内容有动态变化的场景,如果标签页在APP中是静态固定的格局,则可以在无状态控件中加入简易版的DefaultTabController以提高运行效率,毕竟无状态控件要比有状态控件更省资源,运行效率更快。
- TabBar
Tab页的Title控件,切换Tab页的入口,一般放到AppBar控件下使用,内部有*Title属性。其子元素按水平横向排列布局,如果需要纵向排列,请使用Column或ListView控件包装一下。子元素为Tab类型的数组。
- TabBarView
Tab页的内容容器,其内放置Tab页的主体内容。子元素可以是多个各种类型的控件。
三,构造函数
- TabController
- DefalutTabController
const DefaultTabController({
Key key,
@required this.length,
this.initialIndex = ,
@required this.child,
}) : assert(initialIndex != null),
assert(length >= ),
assert(initialIndex >= && initialIndex < length),
super(key: key); - TabController
TabController({ int initialIndex = , @required this.length, @required TickerProvider vsync })
: assert(length != null && length >= ),
assert(initialIndex != null && initialIndex >= && (length == || initialIndex < length)),
_index = initialIndex,
_previousIndex = initialIndex,
_animationController = AnimationController.unbounded(
value: initialIndex.toDouble(),
vsync: vsync,
);
- DefalutTabController
- TabBar
/**
const TabBar({
Key key,
@required this.tabs,//显示的标签内容,一般使用Tab对象,也可以是其他的Widget
this.controller,//TabController对象
this.isScrollable = false,//是否可滚动
this.indicatorColor,//指示器颜色
this.indicatorWeight = 2.0,//指示器高度
this.indicatorPadding = EdgeInsets.zero,//底部指示器的Padding
this.indicator,//指示器decoration,例如边框等
this.indicatorSize,//指示器大小计算方式,TabBarIndicatorSize.label跟文字等宽,TabBarIndicatorSize.tab跟每个tab等宽
this.labelColor,//选中label颜色
this.labelStyle,//选中label的Style
this.labelPadding,//每个label的padding值
this.unselectedLabelColor,//未选中label颜色
this.unselectedLabelStyle,//未选中label的Style
}) : assert(tabs != null),
assert(isScrollable != null),
assert(indicator != null || (indicatorWeight != null && indicatorWeight > 0.0)),
assert(indicator != null || (indicatorPadding != null)),
super(key: key);
*/- Tab
const Tab({
Key key,
this.text,
this.icon,
this.child,
}) : assert(text != null || child != null || icon != null),
assert(!(text != null && null != child)), // TODO(goderbauer): https://github.com/dart-lang/sdk/issues/34180
super(key: key);
- Tab
- TabBarView
const TabBarView({
Key key,
@required this.children, //Tab页内容页组件数组集合
this.controller, //TabController对象
this.physics,
this.dragStartBehavior = DragStartBehavior.start,
}) : assert(children != null),
assert(dragStartBehavior != null),
super(key: key);
四,创建标签栏
- 1.创建TabController
- 使用默认的DefaultController
/**2.创建Tabbar */
@override
Widget build(BuildContext context) {
// TODO: implement build
return new DefaultTabController(
length: myTabs.length,
child: new Scaffold(
//AppBar
appBar:new AppBar(
title: new Text('顶部标签栏'),
bottom: new TabBar(
tabs: myTabs, //标签数组
indicatorColor: Colors.blue,//指示器的颜色
isScrollable: true,//是否滑动
),
) , /**3.绑定Tabbar 和 TabBarView */
//body
body: new TabBarView(
children: myTabs.map((Tab tab){
return new Center( child: new Text(tab.text));
}).toList(),
),
),
);
} - 使用自定义的TabController的
class TabBarDemoState extends State<TabBarDemo>
with SingleTickerProviderStateMixin {
TabController _tabController; //定义tabcontroller变量 @override
void dispose() {
_tabController.dispose(); //销毁
super.dispose();
} void initState() {
super.initState();
_tabController = new TabController(vsync: this, length: ); //创建
} @override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('顶部tab切换'),
bottom: new TabBar(
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.directions_bike),
),
new Tab(
icon: new Icon(Icons.directions_boat),
),
new Tab(
icon: new Icon(Icons.directions_bus),
),
],
controller: _tabController, //tabbar与自定义的tabcontroller绑定
),
),
body: new TabBarView(
controller: _tabController, //tabbarView与 自定义的tabController绑定
children: <Widget>[
new Center(child: new Text('自行车')),
new Center(child: new Text('船')),
new Center(child: new Text('巴士')),
],
),
);
}
- 使用默认的DefaultController
- 2.构建Tab数据/TabBarView数据
/**1. 创建Tab数据 */
final List<Tab> myTabs = <Tab>[
new Tab(icon: new Icon(Icons.home),
text:'首页',
),
new Tab(
icon: new Icon(Icons.message),
text:'个人信息',
), new Tab(
icon: new Icon(Icons.camera),
text:'朋友圈',
),
new Tab(
icon: new Icon(Icons.access_alarm),
text: '闹钟',
)
]; - 3. 创建Tabbar
appBar:new AppBar(
title: new Text('顶部标签栏'),
bottom: new TabBar(
tabs: myTabs, //标签数组
indicatorColor: Colors.blue,//指示器的颜色
isScrollable: true,//是否滑动
),
) - 4.绑定TabBar 和 TabBarView
/**3.绑定Tabbar 和 TabBarView */
//body
body: new TabBarView(
children: myTabs.map((Tab tab){
return new Center( child: new Text(tab.text));
}).toList(),
), - 5.全部代码
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
title: '顶部标签栏',
theme: new ThemeData(
primaryColor: Colors.red
),
home: new App(),
);
}
} class App extends StatelessWidget { /**1. 创建Tab数据 */
final List<Tab> myTabs = <Tab>[
new Tab(icon: new Icon(Icons.home),
text:'首页',
),
new Tab(
icon: new Icon(Icons.message),
text:'个人信息',
), new Tab(
icon: new Icon(Icons.camera),
text:'朋友圈',
),
new Tab(
icon: new Icon(Icons.access_alarm),
text: '闹钟',
)
]; /**2.创建Tabbar */
@override
Widget build(BuildContext context) {
// TODO: implement build
return new DefaultTabController(
length: myTabs.length,
child: new Scaffold(
//AppBar
appBar:new AppBar(
title: new Text('顶部标签栏'),
bottom: new TabBar(
tabs: myTabs, //绑定标签数组
indicatorColor: Colors.blue,//指示器的颜色
isScrollable: true,//是否滑动
),
) , /**3.绑定Tabbar 和 TabBarView */
//body
body: new TabBarView(
children: myTabs.map((Tab tab){
return new Center( child: new Text(tab.text));
}).toList(),
),
),
);
}
}
五,总结
TabBarView和TabBar都有一个TabController的参数,TabbarView和TabBar就是由TabController来控制同步,点击某个Tab后,要同步显示对应的TabBarView,创建TabController有两种方式:
- 第一种:使用系统自带的DefaultTabController,在Scaffold套一层DefaultTabController,这种方式TabBarView会自动查找这个tabController。
@override
Widget build(BuildContext context) {
return new DefaultTabController();
} - 第二种是自己定义一个TabController,实现SingleTickerProviderStateMixin
参考上面“使用自定tabcontroller代码”
【Flutter学习】基本组件之TabBar顶部导航的更多相关文章
- Flutter学习笔记(17)--顶部导航TabBar、TabBarView、DefaultTabController
如需转载,请注明出处:Flutter学习笔记(17)--顶部导航TabBar.TabBarView.DefaultTabController 上一篇我们说了BottmNavigationBar底部导航 ...
- 【Flutter学习】基本组件之AppBar顶部导航栏
一,概述 AppBar 显示在app的顶部.AppBar包含5大部分,如下图: 二,构造函数及参数含义 构造函数 AppBar({ Key key, this.leading, //在标题前面显示的一 ...
- 【Flutter学习】组件学习之目录
01. Flutter组件-Layout-Container-容器 02. Flutter组件-Text-Text-文本 03. Flutter组件-Text-RichText-富文本 04. ...
- 【Flutter学习】组件通信(父子、兄弟)
一,概述 flutter一个重要的特性就是组件化.组件分为两种状态,一种是StatefulWidget有状态组件,一种是StatelessWidget无状态组件. 无状态组件不能更新状态,有状态组件具 ...
- Flutter学习笔记(16)--Scaffold脚手架、AppBar组件、BottomNavigationBar组件
如需转载,请注明出处:Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解 今天的内容是Scaffold脚手架.AppBar组件.BottomNavigationBa ...
- uni-app 去除顶部导航栏
自学uni-app第一天,因为有一点点的小程序和vue的基础所以感觉对uni-app有一点点的亲切感,从今天呢开始着手从登录页学习uni-app,记录一些用到的知识点,欢迎大家一起学习. 启动页隐藏顶 ...
- Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解
如需转载,请注明出处:Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解 最近一段时间生病了,整天往医院跑,也没状态学东西了,现在是好了不少了,也该继续学习啦!!! ...
- Flutter学习笔记(18)--Drawer抽屉组件
如需转载,请注明出处:Flutter学习笔记(18)--Drawer抽屉组件 Drawer(抽屉组件)可以实现类似抽屉拉出和推入的效果,可以从侧边栏拉出导航面板.通常Drawer是和ListView组 ...
- Flutter学习笔记(24)--SingleChildScrollView滚动组件
如需转载,请注明出处:Flutter学习笔记(23)--多 在我们实际的项目开发中,经常会遇到页面UI内容过多,导致手机一屏展示不完的情况出现,以Android为例,在Android中遇到这类情况的做 ...
随机推荐
- objc_setAssociatedObject 关联对象
使用场景:在分类中,不允许创建实例变量,这里就解决了此问题 参考: https://www.cnblogs.com/someonelikeyou/p/7162613.html 属性的实质:就是实例变量 ...
- 2017 山东一轮集训 Day2 Shadow (三维凸包点在面上投影)
在三维坐标中,给定一个点光源,一个凸多面体,以及一个平面作为地面. 求该凸多面体在地面上阴影的面积. 这三个点共同确定了一个平面,这个平面就是地面.保证这三个点坐标互异且不共线.前三行每行三个实数,每 ...
- 计算机网络体系之OSI模型
1.计算机网络体系结构 计算机网络体系结构指的是计算机网络层次模型和各层协议的集合.计算机网络按照高度结构化设计方法采用功能分层原理来实现. 2.OSI模型 网络协议是计算机网络必不可少的,一个完整的 ...
- Orcad Capture元件库介绍--Cadence Allegro
绘制原理图和PCB,最好有自己的元件封装.元件库 ORCAD CAPTURE元件库介绍 AMPLIFIER.OLB amplifier 共182个零件,存放模拟放大器IC,如CA3280,TL027C ...
- 【Java】定义Logger为什么要用static和final?
private static final Logger logger= LoggerFactory.getLogger(ShiroConfig.class); (1)出于资源利用的考虑,Logger的 ...
- linux 文件及目录结构体系
linux 目录的特点: 1). /是所有目录的顶点 2).目录结构像一颗倒挂的树 3).目录和磁盘分区是没有关联的 4)./下不同的目录可能对应不同的分区或磁盘 5).所有的目录都是按照一定的类别有 ...
- Java程序执行的过程
ava程序执行的过程: Step1:将字节码加入内存: Step2:对字节码进行合法性检查: Step3:jvm会为每个字节码文件都生成一个对象(class): Step4:执行静态代码块,初始化静态 ...
- Js事件分发与DOM事件流
这一篇比较透彻:https://www.jianshu.com/p/dc1520327022 点击了目标节点后,捕获阶段里事件会从外向目标传递:到了目标阶段,捕获和冒泡的执行顺序按照事件被定义的先后顺 ...
- Java学习之线程间通信(双线程)
线程间通讯:多个线程在处理同一资源,但是任务不同 练习一:双线程出现线程安全问题,需要使用同步,思考同步代码添加位置需求:银行账户存钱,显示谁在账户存钱了,存了多少钱分析:操作同一银行账户两个不同的操 ...
- Android深度探索-卷1第二章心得体会
这章介绍了搭建Android开发环境的的搭建,主要是在Linux上搭建Android开发环境总体来说因为都是在Linux下开发的,so,只介绍了在Linux环境下的搭建在搭建过程中全是命令操作,和Wi ...