CustomScrollView:如何实现Flutter吸附的效果?

在Android上,这通常是通过AppBarLayout + CoordinatorLayout + CollapsingToolbarLayout来实现的。那么在Flutter中如何实现这样的效果呢?
这里我们先来看一个概念,叫做CustomScrollView。
CustomScrollView
官方文档是这样解释的。 ScrollView
,使用 slivers
创建自定义滚动效果。
CustomScrollView
允许您直接提供slivers
来创建各种滚动效果,例如列表、网格和扩展标题。
如果您要创建一个包含可扩展应用程序栏、后跟列表和网格的滚动视图,您可以使用以下三个选项:SliverAppBar
、❙❙ 和❀♸ 和❀ SliverGrid。这些 slivers
中的
小部件必须创建 RenderSliver
对象。
如果要控制这些滚动视图的初始滚动偏移量,可以使用 控制器
及其属性 ScrollController.initialScrollOffset
设置它。包含灵活的固定应用程序栏、网格和无限列表的视图。
class CustomWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: 150.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('Available seats'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_circle),
tooltip: 'Add new entry',
onPressed: () {
/* ... */
},
),
]),
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: Text('grid item $index'),
);
},
childCount: 20,
),
),
SliverFixedExtentList(
itemExtent: 50.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('list item $index'),
);
},
),
),
],
);
}
}
复制代码
效果如下图SliverAppBar
,两者一起展示。
SliverAppBar
定义:使用CustomScrollView
的Material Design应用程序栏。
应用程序栏由工具栏和可能的其他小部件组成,例如TabBar
和 Flexible SpaceBar
。应用程序栏通常通过按钮 IconButton
公开一项或多项常见操作,也可以选择在后面添加 PopupMenuButton
,后者可以执行一些常见操作。
Sliver 应用程序栏通常用作 CustomScrollView
的第一个子级,并且可以根据滚动视图中其他子级的滚动偏移量动态调整其高度。如果您想使用固定高度的应用栏,您可以看到 AppBar
并在 Scaffold.appBar
中使用它。
此应用程序栏显示一些工具栏小部件,start
(最左边的按钮)、title
和 全部位于上面的 bottom。如果小部件flexibleSpace
也分配了内容,它将被放置在工具栏和底部小部件的下方。
下面的代码可以使用【CustomScrollView.slivers】CustomScrollView
:
SliverAppBar(
expandedHeight: 150.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('Available seats'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_circle),
tooltip: 'Add new entry',
onPressed: () { /* ... */ },
),
]
)
复制代码
将这段代码放在CustomScrollView示例代码中效果如下: ,内容主要是对不同值的详细分析浮动
、捕捉
和固定应用程序❙‸条形应用程序
交互效果影响的变化。
动画预览
App bar -- [浮动]: false, [固定]: false, [捕获]: false:
现象描述:
- 向上滑动时:AppBar第一个区域扩展 > 应用栏弹出->列表弹出
- 向下滚动时:列表向后滚动->应用面板向后滚动->扩展区域向后滚动
应用面板 -- [浮动]:true,[固定]: false , [ snap]: false:
现象描述:
- 向上滑动时:AppBar扩展区域先滑入->appbar面板滑出->列表滑出
- 向下滑动时:应用栏面板向后滑动 -> 滑出区域向后滚动 -> 列表向后滚动
应用栏 -- [floating]: true, [pinned]: false, [pinned]: true:
现象描述:
- 向上滚动时:AppBar 首先展开区域 将其粘贴 -> 应用栏弹出 -> 列表弹出
- 向下滚动时:应用栏弹出 -> 展开的区域动画并直接展开到检测到轻微向下加速度时列表 -> 列表滚动返回
AppBar -- [floating]: true, [pinned]: true, [pinned]: false:
现象描述:当
- 向上滚动:AppBar 扩展区域先关闭 -> 滑出列表
- 向下滚动时:扩展区域向后滚动 -> 列表向后滚动
应用栏 -- [floating]: true, [pinned]: true, [pinned ]: true :
现象描述:
- 向上滚动时:先插入 AppBar 展开区域 -> 弹出列表
- 向下滚动时:检测到轻微加速度时,先插入展开区域动画并直接在列表上方展开 -> 列表向后滚动
AppBar with [floating]: false, [pinned]: true, [capturing]: false:
现象描述:
- 向上滚动时:AppBar 扩展区域首先关闭 -> 弹出列表
- 向下滑动时:列表向后滚动 -> 扩展区域向后滚动
作者:二师兄Snap
属性float
为true时才能设置该属性.
总结下来
固定
最容易理解的就是固定应用程序栏,不要滑出屏幕
,其中出现浮动的,将应用程序重新排序下来,它将出现应用程序面板(和扩展区域)优先级>列表优先级。
snap
结合float
,当检测到轻微的滑动加速时,应用程序面板将以动画方式完全展开以覆盖列表。
我们在这里注意到的一个现象是,当缓慢连续向下滚动时,snap
的真值和假值相差不大。
本文分支的示例代码已上传到github并fork到CustomScrollView分支。
链接:https://juejin.im/post/5d0274846fb9a07edd2a0d4c
来源:掘金致作者商业转载请联系作者授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。