1. 基本介绍
TabBar、TabBarView,TabController 提供了常见的多Tab切换的功能。本文接着 Flutter 组件之 TabBar 详解继续讲解。
2. 示例代码
代码下载地址。如果对你有帮助的话记得给个关注,代码会根据我的 Flutter 专题不断更新。
3. 属性介绍
TabBarView属性 | 介绍 |
---|---|
children | 子页面,注意保持 TabBarView.children 数量、DefaultTabController.length, TabBar.tabs 三者数量相同。 |
controller | TabController,联动控制,下文中自行感受一下,可以关掉 TabBar 或者 TabBarView 的 controller 属性感受一下。 |
physics | 滑动效果,如滑动到末端时,继续拉动,使用 ClampingScrollPhysics 实现Android下微光效果。使用 BouncingScrollPhysics 实现iOS下弹性效果。 |
dragStartBehavior | 启动时阻尼效果,默认为 DragStartBehavior.start |
4. TabBarView 组件
4.1 容器创建
优雅的编程,首先创建一个 tabbarview.dart 文件。先直接创建一个 TabBar 组件,Flutter 组件之 TabBar 详解 已经介绍的很详细了,不多叙述。
import 'package:flutter/material.dart';
class FMTabbarViewVC extends StatefulWidget {
@override
FMTabbarViewState createState() => FMTabbarViewState();
}
class FMTabbarViewState extends State {
var pageDatas = [];
TabController controller;
@override
void initState(){
super.initState();
initData();
controller = TabController(length: pageDatas.length, vsync: ScrollableState());
}
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,
),
),
);
}
TabBar _tabBar(){
return TabBar(
tabs: _tabs(),
isScrollable: true,
indicatorColor: Colors.red,
indicatorWeight: 5,
controller: controller,
onTap: (index){
print("点击了 index = ${index}");
},
);
}
List _tabs(){
List tabList = [];
pageDatas.forEach((page) {
tabList.add(
Tab(text: page["title"],),
);
});
print(tabList);
return tabList;
}
}
4.2 创建 TabBarView
Widget build(BuildContext context) {
// TODO: implement build
return DefaultTabController(
length: pageDatas.length,
child: Scaffold(
appBar: AppBar(
title: Text('TabBar'),
bottom: _tabBar(),
),
body: _tabBarView(),
),
);
}
TabBarView _tabBarView(){
return TabBarView(
children: _tabViews(),
controller: controller,
);
}
List _tabViews(){
List tabViewList = [];
pageDatas.forEach((page) {
var contents = page["content"];
tabViewList.add(
ListView(
children: _listViewChildren(contents),
),
);
});
print(tabViewList);
return tabViewList;
}
List _listViewChildren(List contents){
List children = [];
contents.forEach((content) {
children.add(
ListTile(title: Text("${content}"),)
);
});
return children;
}
到这里其实一个联动的自定义数据的 tabBarView 已经完成了。
4.3 physics
使用 physics 完成一些物理效果,使用 ClampingScrollPhysics 实现Android下微光效果。使用 BouncingScrollPhysics 实现iOS下弹性效果。
TabBarView _tabBarView(){
return TabBarView(
children: _tabViews(),
physics: BouncingScrollPhysics(
),
controller: controller,
);
}
这里就不截图了,建议滑到最后一页继续滑动感受一下。
4.4 dragStartBehavior
启动阻尼,默认为 DragStartBehavior.start,还有个 DragStartBehavior.down,编译后自行体验效果吧。
TabBarView _tabBarView(){
return TabBarView(
children: _tabViews(),
physics: BouncingScrollPhysics(
),
dragStartBehavior: DragStartBehavior.down,
controller: controller,
);
}
4.5 常见报错
Controller's length property (5) does not match the number of tabs (1) present in TabBar's tabs property.
注意:当 TabBarView.children 数量与 Tabs 数量不同时,会报错。注意保持 TabBarView.children 数量、DefaultTabController.length, TabBar.tabs 三者数量相同。
5. 技术小结
- TabBarView 的属性较少。
- TabBarView.children 数量、DefaultTabController.length, TabBar.tabs 三者数量必须相同。
- TabBarView 可以理解为一个特殊的容器,主要的还是子控件的布局,可以使用任意组件。
- 使用好 TabController 控制联动效果。