本文正在参与「金石方案 . 分割6万现金大奖」
1. 前言: 问题引进
FlexibleSpaceBar
是一个和 SliverAppBar
共生的组件,一般不单独运用。如下所示,在滑动的进程中 FlexibleSpaceBar
的 title
区域会有缩放的作用。仔细观察会发现,这个缩放是对整个 title
组件收效的,比方 悉数笔记
和 1590 项笔记
文字都有缩放作用。
上滑 | 下滑 |
---|---|
那问题来了,怎么只让 悉数笔记
的标题有缩放作用,下面的副标题在滑动进程中一向坚持不变呢?或许咱们怎么监听滑动的分率,完结一些自定义的改换作用呢?这就要从 FlexibleSpaceBar
组件的源码中寻找答案,看它是否支撑这种作用,假如不支撑,咱们该怎么自己完结。
2. 探究: FlexibleSpaceBar 组件的标题怎么完结缩放?
在滑动中,title
组件的内容有缩放作用是实事,这说明在组件的 构建逻辑
中必定存在缩放的改换。所以摆在咱们面前的第一个问题是:
FlexibleSpaceBar 组件的标题怎么
完结缩放
的?
FlexibleSpaceBar
是一个 StatefulWidget
,它依赖于 _FlexibleSpaceBarState
状况类来构建组件。所以缩放改换的逻辑也应该在 _FlexibleSpaceBarState#build
办法中:
class FlexibleSpaceBar extends StatefulWidget {
//略...
@override
State<FlexibleSpaceBar> createState() => _FlexibleSpaceBarState();
}
如下所示,在 _FlexibleSpaceBarState#build
中经过 Transform
完结对标题的缩放,缩放运用的矩阵对象是 scaleTransform
:
3. 探究: FlexibleSpaceBar 组件是怎么感知滑动数据的?
从上面作用中能够看出,SliverAppBar
滑动距离和剩下空间的比值,会作为缩放数值的依据。那么摆在咱们面前的第一个问题是:
FlexibleSpaceBar 组件是怎么感知
滑动数据
的?
如下,是 scaleTransform
矩阵的生成进程,其间的缩放值是一个 补间值
,起始值是 widget.expandedTitleScale
,也便是初始的缩放值,默认为 1.5
。也便是说默认情况下,title
组件会被放大 1.5
倍,然后依据 t
值的大小,向 1
进行补间核算。
比方 t = 0.5
时, scaleValue
的值就在 1.5
和 1
的正中间,即 1 + (1.5-1)*0.5 = 1.25
,以此类推。现在的关键便是这个 t
是怎么核算的,滑动的数据信息是谁,经过什么渠道 "贩卖的"
:
---->[_FlexibleSpaceBarState#build]----
final double scaleValue = Tween<double>(begin: widget.expandedTitleScale, end: 1.0).transform(t);
final Matrix4 scaleTransform = Matrix4.identity()
..scale(scaleValue, scaleValue, 1.0);
如下是 t
值的核算进程,能够看出滑动的数据是由 FlexibleSpaceBarSettings
组件记载的,毫无疑问,它是一个 InheritedWidget
, 子树能够经过它拜访存储的信息,本质上和 Theme
一族是一样的。当 t
为 0
时,表明彻底展开的状况;t
为 1
时,表明 SliverAppBar
剩下空间彻底收起:
4. 探究: FlexibleSpaceBarSettings 组件在何时入树的?
现在进入最后一个问题,FlexibleSpaceBarSettings
是何时进入组件树的,其间记载的信息又是怎么放入其间的。在 FlexibleSpaceBar
中有一个静态办法,如下所示,会在入参 child
组件的上层包裹住 FlexibleSpaceBarSettings
,其间持有的信息都是经过入参传递的。如下其注释中也有提及:
也便是说,觉得存入的滑动信息是 FlexibleSpaceBar#createSettings
办法的调用者。到这就好办了,想要知道办法何时被调用的,调试来帮忙。
如下能够看出,是在 _SliverAppBarDelegate
中被调用的。它最终会作为 SliverPersistentHeader
组件的代理类,用于 _SliverAppBarState
的构建逻辑中。
到这儿就万事俱备了,从上滑的分析能够知道,滑动的信息从 FlexibleSpaceBarSettings
中能够获取到。另外,FlexibleSpaceBar
状况类的构建逻辑在处理改换时是比较死的,没有露出给运用者可操作性的空间。所以需求完结一些自定义的改换作用,能够 copy
一下 FlexibleSpaceBar
的源码,来魔改一下。
5. 支撑固定副标题
现在来完结一下固定副标题,作用如下,在滑动进程中 1590 项笔记
副标题一向坚持不变。
上滑 | 下滑 |
---|---|
现在将源码拷贝一份,命名为 DiyFlexibleSpaceBar
,在其间定义 fixedSubtitle
结构入参,作为副标题的插槽。
final Widget? fixedSubtitle;
然后在源码组件状况类的 构建逻辑
中,经过 Column
供给一个插槽即可,如下所示:
然后运用 DiyFlexibleSpaceBar
组件,供给 fixedSubtitle
组件即可:
6. 将滑动分度值露出出去
有时候咱们期望监听到滑动的进展,从而能够在 DiyFlexibleSpaceBar
外部,处理自定义的滑动作用。比方下图中,标题的右侧有一个小风车,能够随着滑动的进展旋转:
上滑 | 下滑 |
---|---|
首先,定义一个 FractionalBuilder
的函数类型,用于回调 t
数值来返回组件 Widget
; 然后在 DiyFlexibleSpaceBar
中定义 titleIconBuilder
成员:
typedef FractionalBuilder = Widget Function(double t);
class DiyFlexibleSpaceBar extends StatefulWidget {
const DiyFlexibleSpaceBar({
/// 略...
this.titleIconBuilder,
final FractionalBuilder? titleIconBuilder;
在构建逻辑在触发 titleIconBuilder
结构组件,参数 t
就能够从这儿露出出去:
然后外界能够感知到 t
的存在,以此操控风车旋转视点即可。关于风车的绘制,参阅 《Flutter 绘制集录 | 第四画 – 风车》
Flutter
供给的组件,只能满意大多数的运用场景,关于特别的需求,可能是不支撑的。这时便是检测一位编程者能力的机遇了,能看懂源码,并能以此进行改善,来完结需求就显得极为重要。希望我们能够在日常开发中 多做推敲
,而不是遇事就 伸手去要
。 那本文就到这儿,谢谢观看 ~