flutter第十五篇:【滚动】总结

Scrollable继承了StatefulWidget。

Viewport继承了MultiChildRenderObjectWidget,MultiChildRenderObjectWidget继承了RenderObjectWidget,RenderObjectWidget继承了Widget。

Sliver继承了

ListView的默认构造函数不是按需加载的,会一次性把所有item都渲染出来。而其他命名构造函数是按需加载的,不会一次性把所有item都渲染出来,而是只会渲染viewport加上下cacheExtent区域的item。

 

1、用SingleChildScrollView包裹Column

SingleChildScrollView不是基于Sliver的按需加载模型,所以最好不要用在内容超出屏幕很多的场景,否则性能会很差。

2、CustomScrollView

CustomScrollView继承了ScrollView,ScrollView继承了StatelessWidget。

return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            expandedHeight: 200.0,
            flexibleSpace: FlexibleSpaceBar(
              title: const Text('Sliver介绍与使用场景'),
              background: Image.network(
                'https://avg-oss.xndm.tech/test/op/yno2JWyRw4sutHx2JCZJYn.jpg',
                fit: BoxFit.cover,
              ),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return ListTile(
                  title: Text('Item $index'),
                );
              },
              childCount: 20,
            ),
          ),
          SliverGrid(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    margin: const EdgeInsets.all(5),
                    height: 100,
                    decoration:
                        BoxDecoration(border: Border.all(color: Colors.black)),
                    child: Text('Item $index'),
                  );
                },
                childCount: 10,
              ),
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2)),
          SliverToBoxAdapter(
            child: Column(
              children: List.generate(
                  20,
                  (int index) => Container(
                        margin: const EdgeInsets.only(
                            left: 10, right: 10, bottom: 5),
                        height: 100,
                        color: Colors.primaries[index % 10],
                      )),
            ),
          )
        ],
      ),
    );

上例中,CustomScrollView包含4个Sliver,分别是用SliverAppBar实现的可伸缩头部、用SliverList实现的滚动列表、用SliverGrid实现的滚动单元格、用SliverToBoxAdapter实现的滚动列表。

3、NestedScrollView
NestedScrollView是一个可以嵌套其他滚动视图的滚动视图,两个滚动视图的的滚动位置有内在联系。最常见的用法是,用headerSliverBuilder构造一个包含TabBar的SliverAppBar,用body指定一个TabBarView,这样可滚动视图的内容就能根据tab切换了。在常规的ScrollView中,有一组sliver(滚动视图的组件)。如果其中一个sliver承载了一个以相反方向滚动的TabBarView(例如,允许用户在标签页所代表的页面之间水平滑动,而列表则垂直滚动),那么该TabBarView内的任何列表都不会与外部的ScrollView交互。例如,快速滑动内部列表滚到顶部,不会导致外部ScrollView中折叠的SliverAppBar展开。NestedScrollView通过为外部ScrollView和内部的ScrollView(即TabBarView中内部的ScrollView)提供自定义的ScrollController解决了这个问题,将他们连接在一起,以便他们看起来是一个连贯的滚动视图。

在NestedScrollView的外部滚动视图或headerSliverBuilder中使用SliverAppBar,可能需要特殊的配置才能像外部和内部是一个单一的滚动视图(如CustomScrollView)那样工作。固定的SliverAppBar在NestedScrollView中的工作方式与在其他滚动视图(如CustomScrollView)中的工作方式完全相同。SliverAppBar的pinned属性设置为true时,app bar会保持在滚动视图顶部可见。app bar仍然可以在用户滚动时扩展和收缩,但它将保持可见,而不是滚动到视图之外。这在NestedScrollView中自然可行,因为固定的SliverAppBar预计不会移入或移出视口(viewport)的可见部分。当内部或外部ScrollView移动时,app bar会按预期保留。如果app bar处于浮动、固定状态,并使用扩展(expanded)高度,那么

当放置在外部可滚动视图或headerSliverBuilder中时,使用SliverAppBar.floating浮动的SliverAppBar将不会浮动到内部滚动视图或body之上。要浮动,需要利用NestedScrollView的floatHeaderSlivers属性,设为true时,嵌套滚动协调器将优先浮动在header slivers中,然后再将剩余的拖动用于body。

SliverToBoxAdapter是RenderBox和RenderSliver之间的桥梁,能把一个RenderBox包装成一个RenderSliver。headerSliverBuilder构造出

headerSliverBuilder构造的组件集中,可以有SliverToBoxAdapter、SliverPersistentHeader,body则是一个TabBarView。SliverPersistentHeader用于放tab的标题,delegate属性是一个自定义的SliverPersistentHeaderDelegate子类,里面有一个TabBar类型的属性,在build()方法中返回一个容器,容器的子组件是这个TabBar。minExtent、maxExtent都是返回tabBar.preferredSize.height,shouldRebuild()返回false。TabBar的controller属性和TabBarView的controller属性共享同一个TabController实例。

posted on 2025-04-14 18:04  koushr  阅读(57)  评论(0)    收藏  举报

导航