重识 Flutter 用于解决复杂滑动视窗问题的 Slivers - part1

前言
在日常的开发工作中,仅仅使用ListView、ListView.builder等这样的滑动组件就能满足大部分的业务需求,在碰到较为复杂的滑动页面时,加上Slivers系列中的几个常用组件也简单的实现。这也就导致了一些朋友没有较为完整的去了解Slivers系列。那么在重识 Flutter 这个专栏中,从组件的使用到其背后的渲染原理,让我们一起探索Slivers的魅力吧!
视窗是什么? Sliver 是什么?
相信点进这篇文章的朋友,一定会知道ListView这样的滚动组件,滚动组件会提供一个区块,用于滚动的显示内容,但内容很多时,我们只能看到可滚动内容中的部分内容。这个就是视窗(ViewPort),也就是列表的可视区域大小。例如一个ListView的显示区域高度为 500 像素,它列表项总高度可能远远超过 500 个像素,但是它的 ViewPort 仍为 500 像素。
那么 Sliver 是什么呢?我们可以通过ListView.builder(),设置itemCount为 null,构建一个无限的列表内容,只有当我们滚动时,才会动态的去创建需要呈现在视窗中的内容。这个就是Sliver,如果一个滚动组件支持Sliver模型,那么这个组件会将子组件分成很多个 Sliver,只有当 Sliver 出现在视窗中才会构建。
CustomScrollView
像ListView、GridView等组件,在底层实现中都有着对应的Sliver,如SliverList、SliverGrid。Sliver 版本的可滚动组件和非 Sliver 版本的可滚动组件最大的区别就是:Sliver 版本的组件不包含滚动模型(Scrollable),组件自身不能滚动。
所以,如果想要使用 Sliver 系列的组件,就需要给它们添加滚动模型。Flutter 提供了CustomScrollView,做为 Sliver 系列组件运行的容器。CustomScrollView主要的作用就是提供Viewport和一个公共的Scrollable,多个 Sliver 组件共用CustomScrollView的Scrollable,就达到了单一滚动的场景。
CustomScrollView有着许多属性,其中最常用的便是 slivers,用来传入 Sliver 组件列表。就像这样:
有了CustomScrollView组件的帮助,实现复杂的滚动效果,好像不是那么困难。
SliverList
如果需要在一个界面创建多个列表,刚了解 Flutter 的朋友可能会使用Column中包裹多个ListView去实现,就像这样:
但是这样的效果肯定不符合需求,如果想要让它们一起滚动,或添加一些复杂的动画,实现像这样的效果:
那么借助SliverList就能很简单的实现。
SliverList 是Sliver Widget的一种,作用是将 Widget 排列在一个List中,使用 SliverList 需要定义delegate。Sliver delegate是用于描述使用哪种方法对组件进行渲染,通常有两种:static 和 builder。
在 SliverList 中,可以定义两种类型的 delegate:
SliverChildListDelegate:获取需要显示的组件列表。此列表中定义的组件将被立即呈现。不会有任何延迟加载。
SliverChildBuilderDelegate:获取将延迟创建的小部件列表。这意味着随着用户滚动,剩余的组件才会开始渲染。
可以简单的把 ListView 理解为:CustomScrollView + SliverList + SliverChildListDelegate;把 ListView.Builder 理解为:CustomScrollView + SliverList + SliverChildBuilderDelegate。
在了解了 SliverList 需要定义的 delegate 后,那么使用它就和使用 ListView 一样简单:
SliverGrid
SliverGrid与GridView一样,将组件以一行两个或一行多个的形式排列。它除了和 SliverList 一样需要定义一个正常的 delegate 之外,还需要传入gridDelegate,用于描述每行如何显示组件。就像这样:每行最多 4 个,每个组件的宽度是高度的 1.5 倍。
在 SliverGrid 中可以定义两种 gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount:指定一行中有多少列,使用它会自动扩展到屏幕最大宽度。
crossAxisCount 属性是列数
childAspectRatio 属性是宽高比
XXXSpacing 属性是指每个 item 之间的边距
SliverGridDelegateWithMaxCrossAxisExtent: 可以指定列的宽度
maxCrossAxisExtent 是列中的最大宽度
可以把 GridView.builder 理解为:CustomScrollView + SliverGrid + SliverChildBuilderDelegate + gridDelegate
遇到一些简单的需求,也可以使用缩写组件:
SliverGrid.count :SliverGrid + SliverChildListDelegate + SliverGridDelegateWithFixedCrossAxisCount
SliverGrid.extent:SliverGrid + SliverChildListDelegate + SliverGridDelegateWithMaxCrossAxisExtent
SliverGrid 与 SliverList 一起使用即可获得这样的效果:
SliverAppBar
AppBar是大部分应用程序很重要的组件,它位于App的顶部,主要控制一些可操作按钮。在 Flutter 中,常在Scaffold下使用AppBar组件。那么什么是SliverAppBar呢?SliverAppBar Widget 是 Flutter 中用于兼容 CustomScrollView 的,它与 AppBar 组件相同,意味着它具有 AppBar 的所有属性,如:title、actions、leading,但它也有一些额外的参数,如pinned, floating, snap,expandedHeight用于自定义 AppBar 的行为。SliverAppBar 通常作为 CustomScrollView slivers 中的第一个组件。
这就是一个很经典的Material应用程序的AppBar。
SliverAppBar 属性众多,与 AppBar 相同的属性在本文就不过多介绍,主要讲解其特有的属性。
expandedHeight
该属性定义了 AppBar 完全展开时的大小,高度会随着向下滚动而缩小。
pinned
该属性用于确定当用户向下滚动时,AppBar 在屏幕上是否保持可见。
floating
该属性如果设置为 true,则 AppBar 将在用户向上滚动时立即可见。如果为 false 那么只有当滚动到顶部才能可见。
snap
该属性如果设置为 true,那么用户向上滚动一点,即可见完整的 AppBar。使用该属性需要将 floating 设置为 true。
在效果图中能明显看出 snap 和 floating 的明显区别。
flexibleSpace
该属性用于给 AppBar 提供background和collapseMode,还有可以随用户滚动而改变位置的title。
当用户向上滚动时,就会得到视差效果,这是因为collapseMode,它有三种模式:parallax , pin , none。collapseMode默认为CollapseMode.parallax,如果将其设置为pin,那么你将不会得到视差效果,只有简单的淡入淡出。
stretch
使用该属性前,需要先设置CustomScrollView的physics,给它一个弹性效果,在滚动到内容尽头时仍然运行滚动。stretch属性设置为 true 时,会让 FlexibleSpaceBar 与外部组件同步滚动。
stretchModes
当stretch属性设置为true时,此时会触发FlexibleSpaceBar容器放大导致的背景图片变化的一个动画效果->stretchModes。stretchModes有三种属性:
zoomBackground 默认效果,放大背景图片
blurBackground 模糊背景图片
fadeTitle 淡化 title
版权声明: 本文为 InfoQ 作者【编程的平行世界】的原创文章。
原文链接:【http://xie.infoq.cn/article/249f8dcb360ac37f394860b4c】。文章转载请联系作者。










评论