Flutter 中如何同时使用 SliverPersistentHeader 和 TabBarView?

Posted

技术标签:

【中文标题】Flutter 中如何同时使用 SliverPersistentHeader 和 TabBarView?【英文标题】:How Use SliverPersistentHeader and TabBarView Together in Flutter? 【发布时间】:2019-10-13 20:25:57 【问题描述】:

我有带有SliverPersistentHeaderTabBarView 的主页,如下代码:

 @override
  Widget build(BuildContext context) 
    return Scaffold(
      backgroundColor: Theme.of(context).backgroundColor,
      body: DefaultTabController(
        length: 3,
        child: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) 
            return <Widget>[
              SliverAppBar(
                expandedHeight: 250.0,
                floating: false,
                pinned: true,
              ),
              SliverPersistentHeader(
                delegate: _SliverAppBarDelegate(
                  TabBar(
                    labelStyle: TextStyle(
                        fontFamily: 'Raleway',
                        fontSize: 17,
                        fontWeight: FontWeight.w400,
                        color: Theme.of(context).backgroundColor),
                    indicatorColor: Theme.of(context).hintColor,
                    labelColor: Theme.of(context).buttonColor,
                    unselectedLabelColor: Theme.of(context).dividerColor,
                    tabs: [
                      Tab(text: "Menu"),
                      Tab(text: "About"),
                      Tab(text: "Contact"),
                    ],
                  ),
                ),
                pinned: true,
              ),
            ];
          ,
          body: TabBarView(
            children: <Widget>[MenuTab(), AboutTab(), ContactTab()],
          ),
        ),
      ),
    );
  


class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate 
  _SliverAppBarDelegate(this._tabBar);

  final TabBar _tabBar;

  @override
  double get minExtent => _tabBar.preferredSize.height;

  @override
  double get maxExtent => _tabBar.preferredSize.height;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) 
    return new Container(
      child: _tabBar,
    );
  

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) 
    return false;
  


之后我每个选项卡都有单个类,例如下面的代码:

class _AboutTabState extends State<AboutTab> 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
        backgroundColor: Theme.of(context).backgroundColor,
        body: ListView(
      children: <Widget>[
        ListView.builder(
          shrinkWrap: true,
          itemCount: _list.length,
          itemBuilder: (BuildContext context, int index) 
            final _aboutList = _list[index];
            return ExpansionTile(
              title: ListTile(
                title: Padding(
                  padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
                  child: Text(_aboutList.aboutTitle,
                      style: TextStyle(
                          fontFamily: 'Raleway',
                          fontSize: 16,
                          fontWeight: FontWeight.w500,
                          color: Theme.of(context).buttonColor)),
                ),
              ),
              children: <Widget>[
                ListTile(
                  title: Padding(
                    padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
                    child: Text(_aboutList.content,
                        style: TextStyle(
                            fontFamily: 'Raleway',
                            fontSize: 16,
                            fontWeight: FontWeight.w400,
                            color: Theme.of(context).toggleableActiveColor)),
                  ),
                )
              ],
            );
          ,
        ),
      ],
    ));

问题:

当我按照屏幕截图折叠 SliverPersistentHeader 时,我得到了错误的结果。 tnx

【问题讨论】:

【参考方案1】:

_SliverAppBarDelegate() 函数返回一个容器,你可以像这样添加颜色:

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate 
  _SliverAppBarDelegate(this._tabBar);

  final TabBar _tabBar;

  @override
  double get minExtent => _tabBar.preferredSize.height;
  @override
  double get maxExtent => _tabBar.preferredSize.height;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) 
    return new Container(
      color: Colors.white, // ADD THE COLOR YOU WANT AS BACKGROUND.
      child: _tabBar,
    );
  

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) 
    return false;
  

【讨论】:

以上是关于Flutter 中如何同时使用 SliverPersistentHeader 和 TabBarView?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用网格 Flutter 同时滚动小部件

如何让我们的列表持久化,同时在 Flutter 应用程序中导航到不同的屏幕?

如何在 Flutter 中同时滚动多个文本字段

如何使用flutter webRTC在agoraIO上同时处理视频通话

flutter ListView - 如何同时左右对齐?

如何在 Flutter 中使用参数更改英雄动画的持续时间