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前端网发表,如需转载,请注明页面地址。
code前端网


发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。