I. overview
NestedScrollView+TabBar+TabBarView realizes TabBar sliding adsorption on the top.
2. Start coding
This code uses the headerslaverbuilder of nestedscrollview (of course, it can also be implemented by CustomScrollView, and the implementation method is basically the same) to realize the sliding top layout, in which the sliderpersistent header implements the TabBar adsorbed on the top. The TabBarView is placed in the body to realize page switching. (flutter's sliding family is worth learning. This code is rewritten according to the example provided on the official website.)
The following code comments are quite detailed,
@override Widget build(BuildContext context) { double statusBarHeight = MediaQuery.of(context).padding.top; ///Height of rotation chart double _swiperHeight = 326 + 10.0; ///Tip head height double _spikeHeight = 80; ///_appBarHeight is the bottom height of AppBar, kToolbarHeight is AppBar height, statusBarHeight is status bar height double _appBarHeight = _swiperHeight + _spikeHeight - kToolbarHeight - statusBarHeight; return NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ///Sliderappbar can also realize the TabBar adsorbed on the top, but the height is not easy to calculate, and there will always be a blank height of the AppBar, ///So I used the sliverepersistentheader to achieve this effect. In the bottom of slivereappbar, only the layout at the top of TabBar is placed child: SliverAppBar( backgroundColor: Color(0xfff1f1f1), forceElevated: innerBoxIsScrolled, bottom: PreferredSize( child: Container(), preferredSize: Size.fromHeight(_appBarHeight)), ///The retracted part of the top of TabBar flexibleSpace: Column( children: <Widget>[ _swiper(), _spike(), ], ), ), ), ///TabBar at the top SliverPersistentHeader( delegate: _SliverAppBarDelegate(_timeSelection()), pinned: true, ), ]; }, body: TabBarView(controller: _timeTabController, children: <Widget>[ _listItem(), _listItem(), _listItem(), _listItem(), _listItem(), _listItem(), ]), ); }
///TabBar's agent 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; } }
Three, summary
The TabBar effect on the top of the adsorption has been working for me all day. I have tried various methods. I found that the implementation of NestedScrollView is relatively simple. But the adsorption effect of the slaverappbar makes me headache. The height is always miscalculated. There is always a gap at the top of slaverappbar without default APPBar. Finally, there is no way to change the mode. The slaverappentheader is used to achieve the adsorption function. Only the top layout is stored in the slaverappbar. No matter how tossed in the middle, it's a good cat that can catch mice. It's an effective solution.