网站界面技术方案韩漫网站建设
web/
2025/9/25 16:31:16/
文章来源:
网站界面技术方案,韩漫网站建设,c2c交易平台下载,做国外搞笑网站在任何系统的UI框架中#xff0c;动画原理都是类似的#xff0c;即#xff1a;在一段时间内#xff0c;快速地多次改变UI外观#xff1b;由于人眼会产生视觉暂留#xff0c;所以最终看到的就是一个“连续”的动画。
Flutter中对动画进行了抽象#xff0c;主要涉及 Anim…在任何系统的UI框架中动画原理都是类似的即在一段时间内快速地多次改变UI外观由于人眼会产生视觉暂留所以最终看到的就是一个“连续”的动画。
Flutter中对动画进行了抽象主要涉及 Animation、Curve、Controller、Tween这四个角色它们一起配合来完成一个完整动画。
1.基本概念
1. Animation
Animation是一个抽象类它本身和UI渲染没有任何关系而它主要的功能是保存动画的插值和状态。Animation对象是一个在一段时间内依次生成一个区间(Tween)之间值的类。Animation对象在整个动画执行过程中输出的值可以是线性的、曲线的、一个步进函数或者任何其他曲线函数等等这由Curve来决定。
我们可以通过Animation来监听动画每一帧以及执行状态的变化Animation有如下两个方法
addListener()它可以用于给Animation添加帧监听器在每一帧都会被调用。帧监听器中最常见的行为是改变状态后调用setState()来触发UI重建。addStatusListener()它可以给Animation添加“动画状态改变”监听器动画开始、结束、正向或反向见AnimationStatus定义时会调用状态改变的监听器。
2. Curve
动画过程可以是匀速的、匀加速的或者先加速后减速等。Flutter中通过Curve曲线来描述动画过程我们把匀速动画称为线性的(Curves.linear)而非匀速动画称为非线性的。
要使用非匀速动画我们可以通过CurvedAnimation来指定动画的曲线如
final CurvedAnimation curve CurvedAnimation(parent: controller, curve: Curves.easeIn);Curve的关键是实现一个transform方法就是 transform(double t) → double
t是时间点取值是0到1之间。返回值是动画的进展取值也是0到1之间。
3. AnimationController
AnimationController派生自Animationdouble因此可以在需要Animation对象的任何地方使用。 但是AnimationController具有控制动画的其他方法包含动画的启动forward()、停止stop() 、反向播放 reverse()等方法。AnimationController可以在一段时间里生成一个区间默认是0.0到1.0中的值
final AnimationController controller AnimationController( duration: const Duration(milliseconds: 2000), lowerBound: 10.0,upperBound: 20.0,vsync: this
);4. Tween
默认情况下AnimationController对象值的范围是[0.01.0]。如果我们需要构建UI的动画值在不同的范围或不同的数据类型则可以使用Tween来添加映射以生成不同的范围或数据类型的值。例如
final Tween colorTween ColorTween(begin: Colors.transparent, end: Colors.black54);Tween继承自AnimatableT而不是继承自AnimationTAnimatable中主要定义动画值的映射规则。
Tween对象不存储任何状态相反它提供了evaluate(Animationdouble animation)方法它可以获取动画当前映射值。 Animation对象的当前值可以通过value()方法取到。evaluate函数还执行一些其他处理例如分别确保在动画值为0.0和1.0时返回开始和结束状态。
要使用 Tween 对象需要调用其animate()方法然后传入一个控制器对象。例如以下代码在 500 毫秒内生成从 0 到 255 的整数值。
final AnimationController controller AnimationController(duration: const Duration(milliseconds: 500), vsync: this,
);
Animationint alpha IntTween(begin: 0, end: 255).animate(controller);5.CurveTween
CurveTween有别于Tween的是它不能指定动画值的上下限它的作用是根据指定的Curve来转换animation的值。Tween可以通过chain来组合CurveTween实现指定区间的动画曲线。
6.CurvedAnimation
CurvedAnimation是将动画曲线应用到已有Animation来生成一个新的Animation。
简单论述下几者的关系animated之间可以chainanimated可以对已有animation进行animate来生成新的animationanimation可以drive animated来生成animationcontroller是一个完备的animation可以直接使用除非数值区间或者动画曲线不符合要求。基于以上论述以下代码是等效的
//1
final Animationdouble cAnimation1 CurvedAnimation(parent: controller,curve: Curves.ease,
);
final Animationdouble animation Tween(beigin:0.0, end:2.0).animate(cAnimation1)//2
final Animationdouble animation Tween(beigin:0.0, end:2.0).chain(CurveTween(curve: Curves.ease)).animate(controller)//3
final Animationdouble cAnimation2 controller.drive(CurveTween(curve: Curves.ease),
);
final Animationdouble animation Tween(beigin:0.0, end:2.0).animate(cAnimation2)
2.实现细节
1.vsync:this
我们看到前面AnimationController构造函数里有个vsync参数我们把this传了进去而且我们还在this所指向的state混入了SingleTickerProviderStateMixin。我们来看看实现源码
过 vsync 对象创建了一个 _ticker 而传入的 _tick 是一个回调函数。查看源码它是用于更新 value 也就是说 AnimationController.value 是在此回调中发生改变。
我们将视角回调 _ticker vsync.createTicker(_tick); 来看看 Ticker 。
2.Ticker
class Ticker {TickerFuture? _future;bool get muted _muted;bool _muted false;set muted(bool value) {if (value muted)return;_muted value;if (value) {unscheduleTick();} else if (shouldScheduleTick) {scheduleTick();}}bool get isTicking {if (_future null)return false;if (muted)return false;if (SchedulerBinding.instance!.framesEnabled)return true;if (SchedulerBinding.instance!.schedulerPhase ! SchedulerPhase.idle)return true; // for example, we might be in a warm-up frame or forced framereturn false;}protectedbool get shouldScheduleTick !muted isActive !scheduled;void _tick(Duration timeStamp) {assert(isTicking);assert(scheduled);_animationId null;_startTime ?? timeStamp;_onTick(timeStamp - _startTime!);if (shouldScheduleTick)scheduleTick(rescheduling: true);}protectedvoid scheduleTick({ bool rescheduling false }) {assert(!scheduled);assert(shouldScheduleTick);_animationId SchedulerBinding.instance!.scheduleFrameCallback(_tick, rescheduling: rescheduling);}protectedvoid unscheduleTick() {if (scheduled) {SchedulerBinding.instance!.cancelFrameCallbackWithId(_animationId!);_animationId null;}assert(!shouldScheduleTick);}mustCallSupervoid dispose() {if (_future ! null) {final TickerFuture localFuture _future!;_future null;assert(!isActive);unscheduleTick();localFuture._cancel(this);}}
}Ticker 由 SchedulerBinding 驱动。flutter 每绘制一帧就会回调 Ticker._onTick()所以每绘制一帧 AnimationController.value 就会发生变化。
接下来看一下 Ticker 其他成员与方法
muted : 设置为 ture 时钟仍然可以运行但不会调用该回调。isTicking: 是否可以在下一帧调用其回调如设备的屏幕已关闭则返回false。_tick(): 时间相关的计算交给 _onTick()受到 muted 影响。scheduleTick(): 将 _tick() 回调交给 SchedulerBinding 管理flutter 每绘制一帧都会调用它。unscheduleTick(): 取消回调的监听。
_onTick在AnimationController中实现 这里主要更新value、status以及notifyListeners。对于renderObject调用notifyListeners会调用markNeedsPaint方法在下一帧进行重绘。
把_onTick传入创建Ticker的方法 3.SingleTickerProviderStateMixin
optionalTypeArgs
mixin SingleTickerProviderStateMixinT extends StatefulWidget on StateT implements TickerProvider {Ticker? _ticker;overrideTicker createTicker(TickerCallback onTick) {_ticker Ticker(onTick, debugLabel: kDebugMode ? created by $this : null)return _ticker!;}overridevoid dispose() {super.dispose();}overridevoid didChangeDependencies() {if (_ticker ! null)_ticker!.muted !TickerMode.of(context);super.didChangeDependencies();}}
SingleTickerProviderStateMixin 就是我们在 State 中 vsync:this 它做了一个桥梁连接了 State 与 Ticker 。
以上源码重要一点是在 didChangeDependencies() 中将 muted !TickerMode.of(context) 初始化一遍。 TickerMode是 InheritedWidget 中 widget 中的属性。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81713.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!