一、概述
NestedScrollView+TabBar+TabBarView实现TabBar滑动吸附在顶部。
二、开始编码
本次代码以NestedScrollView(当然也可以用CustomScrollView实现,实现方法基本一致)的headerSliverBuilder实现滑动的顶部布局,其中SliverPersistentHeader实现吸附在顶部的TabBar。body中放TabBarView实现页面切换。(flutter的滑动家族还是值得好好学习一番的。此次代码是根据官网提供的例子而改写的)
以下代码注释还是挺详细的,
@override
Widget build(BuildContext context) {
double statusBarHeight = MediaQuery.of(context).padding.top;
///轮播图高度
double _swiperHeight = 326 + 10.0;
///提示头部高度
double _spikeHeight = 80;
///_appBarHeight算的是AppBar的bottom高度,kToolbarHeight是APPBar高,statusBarHeight是状态栏高度
double _appBarHeight =
_swiperHeight + _spikeHeight - kToolbarHeight - statusBarHeight;
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
///SliverAppBar也可以实现吸附在顶部的TabBar,但是高度不好计算,总是会有AppBar的空白高度,
///所以我就用了SliverPersistentHeader来实现这个效果,SliverAppBar的bottom中只放TabBar顶部的布局
child: SliverAppBar(
backgroundColor: Color(0xfff1f1f1),
forceElevated: innerBoxIsScrolled,
bottom: PreferredSize(
child: Container(),
preferredSize: Size.fromHeight(_appBarHeight)),
///TabBar顶部收缩的部分
flexibleSpace: Column(
children: <Widget>[
_swiper(),
_spike(),
],
),
),
),
///停留在顶部的TabBar
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(_timeSelection()),
pinned: true,
),
];
},
body: TabBarView(controller: _timeTabController, children: <Widget>[
_listItem(),
_listItem(),
_listItem(),
_listItem(),
_listItem(),
_listItem(),
]),
);
}
///TabBar的代理
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar);
final Stack _tabBar;
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return _tabBar;
}
@override
double get maxExtent => 55;
@override
double get minExtent => 55;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
三、总结
吸附顶部的TabBar效果搞了我一整天,尝试了各种办法,兜兜转转发现还是NestedScrollView的实现方式比较简单。但是其中的SliverAppBar的吸附效果搞得我实在头疼,高度总是计算失误,没有默认APPBar的SliverAppBar顶部总是有一段空白,最后没办法只能转变方式,利用SliverPersistentHeader来实现吸附功能,SliverAppBar中只存放顶部的布局。不管中间怎么折腾,能抓住耗子的就是好猫,这也不失为一种有效的解决办法吧。