TabBar + PageView可以说是flutter开发中的经典组合,所以flutter为开发者提供了非常轻松便捷的方式就可以实现TabBar和PageView的联动效果。
原生开发TabBar + PageView还是比较麻烦的,但是flutter几行代码就可以搞定,而且还自带动画效果,还提供了很高的自定义方式。
经典的TabBar是这样的:
代码如下:
TabBar(
labelColor: Colors.blue,
labelStyle: TextStyle(color: Colors.blue, fontSize: 14),
unselectedLabelColor: Colors.black54,
unselectedLabelStyle: TextStyle(color: Colors.black54, fontSize: 14),
isScrollable: true,
controller: _tabController,
onTap: _changeTab,
tabs: _titleList.map((e) => Tab(text: e)).toList(),
)
我们可以自定义成这样子的TabBar:
自定义它的indicator,你可以写成你想要的任何样式,代码如下:
TabBar(
labelColor: Colors.blue,//选中的颜色
labelStyle: TextStyle(color: Colors.blue, fontSize: 14),
unselectedLabelColor: Colors.black54,//未选中的颜色
unselectedLabelStyle: TextStyle(color: Colors.black54, fontSize: 14),
isScrollable: true,
//自定义indicator样式
indicator: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.all(Radius.circular(15))
),
controller: _tabController,
onTap: _changeTab,
tabs: _titleList.map((e) => Tab(text: e)).toList(),
)
这个indicator需要一个decoration,所以我们传入一个BoxDecoration就可以自定义indicator。
接下来就是和PageView的联动,和PageView联动,需要两个controller,一个是控制tab移动的TabController,一个是控制PageView滑动的PageController
class _CustomTabPageState extends State<CustomTabPage> with TickerProviderStateMixin{
TabController _tabController;
PageController _pageController;
List<String> _titleList = <String>['关注','推荐', '抗疫', '热榜', '精品课', '旅游'];
@override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: _titleList.length);
_pageController = PageController();
}
void _changeTab(int index) {
_pageController.animateToPage(index, duration: Duration(milliseconds: 300), curve: Curves.ease);
}
void _onPageChanged(int index) {
_tabController.animateTo(index, duration: Duration(milliseconds: 300));
}
@override
void dispose() {
_pageController.dispose();
_tabController.dispose();
super.dispose();
}
}
首先state需要混入一个TickerProviderStateMixin,这样才可以在构建TabController的时候,vsync参数传入this,这个是因为做动画的需要,具体的说明可以查看基础教程。
然后我们定义两个监听函数,分别监听tab滚动时,调用PageController使页面跟着tab滑动,另外一个监听函数是监听页面滑动时,通过TabController控制tab的移动,最后别忘记在dispose的时候释放这两个controller。
build方法的代码如下
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('自定义TabBar', style: TextStyle(color: Colors.black54),),
backgroundColor: Colors.white,
brightness: Brightness.light,
elevation: 0,
iconTheme: IconThemeData(
color: Colors.black54
),
),
body: Column(
children: <Widget>[
Container(
width: double.infinity,
color: Colors.white,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5),
height: 45,
child: TabBar(
labelColor: Colors.blue,//选中的颜色
labelStyle: TextStyle(color: Colors.blue, fontSize: 14),
unselectedLabelColor: Colors.black54,//未选中的颜色
unselectedLabelStyle: TextStyle(color: Colors.black54, fontSize: 14),
isScrollable: true,
//自定义indicator样式
indicator: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.all(Radius.circular(15))
),
controller: _tabController,
onTap: _changeTab,
tabs: _titleList.map((e) => Tab(text: e)).toList(),
),
),
Expanded(
child: PageView.builder(
physics: BouncingScrollPhysics(),
controller: _pageController,
onPageChanged: _onPageChanged,
itemCount: _titleList.length,
itemBuilder: (context, index) {
return PageItemView(index);
}
)
)
],
),
);
}
最终效果如第一张图所示