1. 基本介绍
TabBar、TabBarView,TabController 提供了常见的多Tab切换的功能,例如电商网站上方横划的服装、家具、电子产品... 等切换页面,然后点击对应 tab 切换到不同专场这种功能。
2. 示例代码
代码下载地址。如果对你有帮助的话记得给个关注,代码会根据我的 Flutter 专题不断更新。
3. 属性介绍
TabBar属性 | 介绍 |
---|---|
controller | TabController,控制联动,Flutter 组件之 TabBarView 详解中有用到 |
isScrollable | 是否可以滚动,默认为 false |
indicatorColor | 指示器颜色 |
indicatorWeight | 指示器宽度 |
indicatorPadding | 指示器间距 EdgeInsets.zero, |
indicator | 自定义指示器 |
indicatorSize | 指示器大小 |
labelColor | title 颜色 |
labelStyle | title 样式 |
labelPadding | title 间距 |
unselectedLabelColor | 未选中 title 颜色 |
unselectedLabelStyle | 未选中 title 样式 |
dragStartBehavior | 拖拽设置,默认为 DragStartBehavior.start, |
mouseCursor | 鼠标悬停,Web可以了解 |
onTap | 点击事件 |
physics | 滑动效果,如滑动到末端时,继续拉动,使用 ClampingScrollPhysics 实现Android下微光效果。使用 BouncingScrollPhysics 实现iOS下弹性效果。 |
4. TabBar 组件
4.1 容器创建
优雅的编程,首先创建一个 tabbar.dart 文件。
import 'package:flutter/material.dart';
class FMTabBarVC extends StatefulWidget {
@override
FMTabBarState createState() => FMTabBarState();
}
class FMTabBarState extends State {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: _tabBar(),
),
body: Container(
color: Colors.grey,
),
);
}
TabBar _tabBar(){
return TabBar(
tabs: [
Tab(
text: "tab1",
),
Tab(
text: "tab2",
),
Tab(
text: "tab3",
),
Tab(
text: "tab4",
),
Tab(
text: "tab5",
),
],
);
}
}
运行上边代码,会有如下报错。TabBar 在使用时必须指定一个 TabController 或者 DefaultTabController。
No TabController for TabBar.
When creating a TabBar, you must either provide an explicit TabController using the "controller" property, or you must ensure that there is a DefaultTabController above the TabBar.
In this case, there was neither an explicit controller nor a default controller.
4.2 正确的 TabController 容器使用
为了修复以上报错,我们在 DefaultTabController 中使用 TabBar 组件。
import 'package:flutter/material.dart';
class FMTabBarVC extends StatefulWidget {
@override
FMTabBarState createState() => FMTabBarState();
}
class FMTabBarState extends State {
@override
Widget build(BuildContext context) {
// TODO: implement build
return DefaultTabController(
length: 5,
child: Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: _tabBar(),
),
body: Container(
color: Colors.grey,
),
),
);
}
TabBar _tabBar(){
return TabBar(
tabs: [
Tab(
text: "tab1",
),
Tab(
text: "tab2",
),
Tab(
text: "tab3",
),
Tab(
text: "tab4",
),
Tab(
text: "tab5",
),
],
);
}
}
注意:length 一定要赋值,并且与 tabs 的数量相同,不然会有以下报错。
The method '>=' was called on null.
Receiver: null
Tried calling: >=(0)
Controller's length property (6) does not match the number of tabs (5) present in TabBar's tabs property.
4.3 封装一个自动填充数据的 TabBar
import 'package:flutter/material.dart';
class FMTabBarVC extends StatefulWidget {
@override
FMTabBarState createState() => FMTabBarState();
}
class FMTabBarState extends State {
var pageDatas = [];
@override
void initState(){
super.initState();
initData();
}
void initData(){
pageDatas.add({"title":"一年级英语", "content":["我是一年级英语一班", "我是一年级英语二班","我是一年级英语三班"]});
pageDatas.add({"title":"二年级英语", "content":["我是二年级英语一班", "我是二年级英语二班","我是二年级英语三班"]});
pageDatas.add({"title":"三年级英语", "content":["我是三年级英语一班", "我是三年级英语二班","我是三年级英语三班"]});
pageDatas.add({"title":"四年级英语", "content":["我是四年级英语一班", "我是四年级英语二班","我是四年级英语三班"]});
pageDatas.add({"title":"五年级英语", "content":["我是五年级英语一班", "我是五年级英语二班","我是五年级英语三班"]});
setState(() {
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return DefaultTabController(
length: pageDatas.length,
child: Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: _tabBar(),
),
body: Container(
color: Colors.grey,
),
),
);
}
DefaultTabController _tabController(){
return DefaultTabController(
length: pageDatas.length,
child: Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: _tabBar(),
),
body: Container(
color: Colors.grey,
),
),
);
}
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: Colors.red,
width: 3
),
),
);
}
List _tabs(){
List tabList = [];
pageDatas.forEach((page) {
tabList.add(
Tab(text: page["title"],),
);
});
print(tabList);
return tabList;
}
}
注意:isScrollable 默认为 false,设置为 true 才可以滑动,否则数据过多时,可能会自适应效果,导致 title 被挤压。
4.4 indicatorColor, indicatorWeight
设置 indicator 颜色和宽度
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 15,
);
}
4.5 indicatorSize
使用 indicatorSize 修改 indicator 大小。
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 15,
indicatorSize: TabBarIndicatorSize.label,
);
}
4.6 indicatorPadding
使用 indicatorPadding 修改 indicator 的位置。
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 15,
indicatorSize: TabBarIndicatorSize.label,
indicatorPadding: EdgeInsets.only(bottom: 15),
);
}
4.7 indicator
使用 indicator 属性自定义 indicator。
注意:此时会优先执行自定义的 indicator,其他的设置会被覆盖掉。
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 15,
indicatorSize: TabBarIndicatorSize.label,
indicatorPadding: EdgeInsets.only(bottom: 15),
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: Colors.red,
width: 3
),
),
);
}
4.8 字体颜色大小设置
具体描述见上方表格。
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 5,
indicatorSize: TabBarIndicatorSize.label,
labelColor: Colors.yellow,
labelStyle: TextStyle(
fontSize: 15,
),
unselectedLabelColor: Colors.black,
unselectedLabelStyle: TextStyle(
fontSize: 12
),
// indicatorPadding: EdgeInsets.only(bottom: 15),
// indicator: UnderlineTabIndicator(
// borderSide: BorderSide(
// color: Colors.red,
// width: 3
// ),
// ),
);
}
4.9 labelPadding
使用 labelPadding 来改变 label 位置。
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 5,
indicatorSize: TabBarIndicatorSize.label,
labelColor: Colors.yellow,
labelStyle: TextStyle(
fontSize: 15,
),
unselectedLabelColor: Colors.black,
unselectedLabelStyle: TextStyle(
fontSize: 12
),
labelPadding: EdgeInsets.only(top: 30,left: 15),
// indicatorPadding: EdgeInsets.only(bottom: 15),
// indicator: UnderlineTabIndicator(
// borderSide: BorderSide(
// color: Colors.red,
// width: 3
// ),
// ),
);
}
4.10 onTap 点击事件
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 5,
indicatorSize: TabBarIndicatorSize.label,
labelColor: Colors.yellow,
labelStyle: TextStyle(
fontSize: 15,
),
unselectedLabelColor: Colors.black,
unselectedLabelStyle: TextStyle(
fontSize: 12
),
labelPadding: EdgeInsets.only(top: 30,left: 15),
// indicatorPadding: EdgeInsets.only(bottom: 15),
// indicator: UnderlineTabIndicator(
// borderSide: BorderSide(
// color: Colors.red,
// width: 3
// ),
// ),
onTap: (index){
print("点击了 index = ${index}");
},
);
}
5. 技术小结
- TabBar 的使用可能会面临很多报错,不要着急。
- TabBar 的 tabs 数量一定要与 TabController 的 length 相同。
- 其他的一些属性配置其实不难,多加练习。