flutter控件----NestedScrollView+TabBar+TabBarView实现折叠顶部布局

一、概述

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中只存放顶部的布局。不管中间怎么折腾,能抓住耗子的就是好猫,这也不失为一种有效的解决办法吧。

源码下载

你可能感兴趣的:(Flutter,Flutter探索记)