前言
在日常的开发工作中,仅仅应用ListView
、ListView.builder
等这样的滑动组件就能满足大部分的业务需要,在碰到较为简单的滑动页面时,加上Slivers
系列中的几个罕用组件也简略的实现。这也就导致了一些敌人没有较为残缺的去理解Slivers
系列。那么在重识Flutter这个专栏中,预计有5篇slivers相干的文章,从组件的应用到其背地的渲染原理,让咱们一起摸索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组件列表。就像这样:
Scaffold( body: CustomScrollView( slivers: [ SliverList(/**/), SliverGrid(/**/), ], ), );
有了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一样简略:
CustomScrollView( slivers: [ SliverList( delegate: SliverChildListDelegate([ Container( height: 50, color: Colors.primaries[0], ), ]), ), SliverList( delegate: SliverChildBuilderDelegate((BuildContext ctx, int index) { return Container( height: 50, color: Colors.primaries[index % Colors.primaries.length], ); }, childCount: 5), ), ], ),
SliverGrid
SliverGrid
与GridView
一样,将组件以一行两个或一行多个的模式排列。它除了和SliverList一样须要定义一个失常的delegate之外,还须要传入gridDelegate
,用于形容每行如何显示组件。就像这样:每行最多4个,每个组件的宽度是高度的1.5倍。
SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, crossAxisSpacing: 5, mainAxisSpacing: 3, childAspectRatio: 1.5), delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( color: Colors.primaries[index % Colors.primaries.length], ); }, childCount: 20),)
在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.count( crossAxisCount: 3, children: [ ...List.generate( 3, (index) => Container( color: Colors.primaries[index % Colors.primaries.length], ), ) ],),SliverGrid.extent( maxCrossAxisExtent: 100, children: [ ...List.generate( 9, (index) => Container( color: Colors.primaries[index % Colors.primaries.length], ), ) ],)
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中的第一个组件。
Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( title: Text("Hello SliverAppBar & Taxze"), actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ], ), ], ),)
这就是一个很经典的Material
应用程序的AppBar
。
SliverAppBar属性泛滥,与AppBar雷同的属性在本文就不过多介绍,次要解说其特有的属性。
expandedHeight
该属性定义了AppBar齐全开展时的大小,高度会随着向下滚动而放大。
SliverAppBar( title: Text("Hello SliverAppBar & Taxze"), expandedHeight: 200, actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ],),
未设置expandedHeight | expandedHeight: 200 |
---|---|
pinned
该属性用于确定当用户向下滚动时,AppBar在屏幕上是否放弃可见。
SliverAppBar( title: Text("Hello SliverAppBar & Taxze"), expandedHeight: 200, pinned: true, actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ],),
pinned: true | pinned: false |
---|---|
floating
该属性如果设置为true,则AppBar将在用户向上滚动时立刻可见。如果为false那么只有当滚动到顶部能力可见。
SliverAppBar( title: Text("Hello SliverAppBar & Taxze"), expandedHeight: 200, floating: true, actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ],),
floating: true | floating: false |
---|---|
snap
该属性如果设置为true,那么用户向上滚动一点,即可见残缺的AppBar。应用该属性须要将floating设置为true。
SliverAppBar( title: Text("Hello SliverAppBar & Taxze"), expandedHeight: 200, floating: true, snap: true, actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ],),
snap: true | floating: true |
---|---|
在效果图中能显著看出snap和floating的显著区别。
flexibleSpace
该属性用于给AppBar提供background
和collapseMode
,还有能够随用户滚动而扭转地位的title
。
SliverAppBar( expandedHeight: 200, flexibleSpace: FlexibleSpaceBar( title: Text("First FlexibleSpace",style: TextStyle(color: Colors.red),), background: Image.network( "https://p3-passport.byteimg.com/img/user-avatar/af5f7ee5f0c449f25fc0b32c050bf100~180x180.awebp", fit: BoxFit.cover), ), actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ],),
当用户向上滚动时,就会失去视差成果,这是因为collapseMode
,它有三种模式:parallax
, pin
, none
。collapseMode
默认为CollapseMode.parallax
,如果将其设置为pin
,那么你将不会失去视差成果,只有简略的淡入淡出。
flexibleSpace: FlexibleSpaceBar( title: Text("First FlexibleSpace",style: TextStyle(color: Colors.black),), collapseMode: CollapseMode.pin, background: Image.network( "https://p3-passport.byteimg.com/img/user-avatar/af5f7ee5f0c449f25fc0b32c050bf100~180x180.awebp", fit: BoxFit.cover),),
CollapseMode.parallax | CollapseMode.pin |
---|---|
stretch
应用该属性前,须要先设置CustomScrollView
的physics
,给它一个弹性成果,在滚动到内容止境时依然运行滚动。stretch
属性设置为true时,会让 FlexibleSpaceBar 与内部组件同步滚动。
SliverAppBar( expandedHeight: 200, pinned: true, stretch: true, flexibleSpace: FlexibleSpaceBar( title: Text("First FlexibleSpace",style: TextStyle(color: Colors.black),), // collapseMode: CollapseMode.pin, background: Image.network( "https://p3-passport.byteimg.com/img/user-avatar/af5f7ee5f0c449f25fc0b32c050bf100~180x180.awebp", fit: BoxFit.cover), ), actions: <Widget>[ IconButton(onPressed: () => null, icon: const Icon(Icons.add)) ],),
stretch: true | stretch: false |
---|---|
stretchModes
当stretch
属性设置为true
时,此时会触发FlexibleSpaceBar
容器放大导致的背景图片变动的一个动画成果->stretchModes
。stretchModes
有三种属性:
- zoomBackground默认成果,放大背景图片
- blurBackground含糊背景图片
- fadeTitle淡化title
flexibleSpace: FlexibleSpaceBar( title: Text("First FlexibleSpace",style: TextStyle(color: Colors.black),), // collapseMode: CollapseMode.pin, background: Image.network( "https://p3-passport.byteimg.com/img/user-avatar/af5f7ee5f0c449f25fc0b32c050bf100~180x180.awebp", fit: BoxFit.cover), stretchModes: [ // StretchMode.fadeTitle, // StretchMode.blurBackground, StretchMode.zoomBackground ],),
zoomBackground | blurBackground | fadeTitle |
---|---|---|
对于我
Hello,我是Taxze,如果您感觉文章对您有价值,心愿您能给我的文章点个❤️,有问题须要分割我的话:我在这里 ,也能够通过掘金的新的私信性能分割到我。如果您感觉文章还差了那么点货色,也请通过关注督促我写出更好的文章~万一哪天我提高了呢?