如何创建一个有界的可滚动TabBarView [英] How to create a bounded scrollable TabBarView

查看:158
本文介绍了如何创建一个有界的可滚动TabBarView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在Flutter中实现以下布局.

I need to implement the following layout in Flutter.

当用户滚动时,我希望整个布局都滚动(隐藏标题和标签栏).但是,我无法将TabBarView嵌套在ListView中,因为TabBarView没有限制的高度,并且ListViews没有为其子代提供限制的高度.

When the user scrolls, I want the entire layout to scroll (hiding the header and tab bar). However, I can't nest a TabBarView inside a ListView since the TabBarView doesn't have a bounded height and ListViews don't provide a bounded height to their children.

我已经看过这些问题,但是对于此用例,所有问题的答案都不能令人满意:

I've already seen these questions, but all of them have unsatisfactory answers for this use case:

  • How can I have a TabView with variable height content within a Scrollable View with Flutter? : Exactly what I needed, but the only answer doesn't provide any concrete code on how to implement this, only a reference to a feature (SliverList) that I can't figure out how to implement.
  • how to implement a sliverAppBar with a tabBar : The provided code doesn't work since the SliverList doesn't accept a constructor with this shape (and I tried adapting it to use a delegate without success).
  • Getting 'Horizontal viewport was given unbounded height.' with TabBarView in flutter : This use case doesn't work for me since I need the entire layout to scroll, and in that answer, the header is fixed to the top.

推荐答案

class SliverWithTabBar extends StatefulWidget {
  @override
  _SliverWithTabBarState createState() => _SliverWithTabBarState();
}

class _SliverWithTabBarState extends State<SliverWithTabBar> with SingleTickerProviderStateMixin {
  TabController controller;

  @override
  void initState() {
    super.initState();
    controller = TabController(length: 3, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return [
            SliverAppBar(
              pinned: false,
              backgroundColor: Colors.white,
              flexibleSpace: FlexibleSpaceBar(
                collapseMode: CollapseMode.pin,
                background: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Container(
                      height: 200.0,
                      width: double.infinity,
                      color: Colors.grey,
                      child: FlutterLogo(),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Text(
                        'Business Office',
                        style: TextStyle(fontSize: 25.0),
                        textAlign: TextAlign.left,
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Text(
                        'Open now\nStreet Address, 299\nCity, State',
                        style: TextStyle(fontSize: 15.0),
                        textAlign: TextAlign.left,
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(right: 10.0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: <Widget>[
                          Icon(Icons.share),
                          Padding(
                            padding: const EdgeInsets.only(left: 10.0),
                            child: Icon(Icons.favorite),
                          ),
                        ],
                      ),
                    )
                  ],
                ),
              ),
              expandedHeight: 380.0,
              bottom: TabBar(
                indicatorColor: Colors.black,
                labelColor: Colors.black,
                tabs: [
                  Tab(text: 'POSTS'),
                  Tab(text: 'DETAILS'),
                  Tab(text: 'FOLLOWERS'),
                ],
                controller: controller,
              ),
            )
          ];
        },
        body: ListView.builder(
          itemCount: 100,
          itemBuilder: (BuildContext context, int index) {
            return Card(
              color: index % 2 == 0 ? Colors.blue : Colors.green,
              child: Container(
                alignment: Alignment.center,
                width: double.infinity,
                height: 100.0,
                child: Text(
                  'Flutter is awesome',
                  style: TextStyle(fontSize: 18.0),
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

您应该寻找Sliver小部件以实现NestedScrollView.

You should look for Sliver widgets to achieve NestedScrollView.

这为您提供了一个 headerSliv​​erBuilder 属性,您可以在其中实际放置一些标题,这些标题可能会在滚动小部件时隐藏或固定在屏幕顶部,在此示例中,为.

That gives you a headerSliverBuilder property where you can actually fit some headers that you might hide or pin on the top of the screen when the body widget is scrolled, in this particular example, a ListView.

您可能想看一下 RenderSliv​​er 文档.

You might want to take a look to the RenderSliver documentation.

这篇关于如何创建一个有界的可滚动TabBarView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆