# flutter-learning-experience **Repository Path**: django_tung/flutter-learning-experience ## Basic Information - **Project Name**: flutter-learning-experience - **Description**: No description available - **Primary Language**: Dart - **License**: AGPL-3.0 - **Default Branch**: release/v1.0 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-12-07 - **Last Updated**: 2021-02-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # flutter 基础与动画能力介绍 ### 缺点 - 学习成本较陡峭 - 需要新的开发语言 dart - flutter 体系较庞大, 需要时间熟悉 - 不支持热更新(虽然有第三方方案) - 不基于原生组件,混合开发没有优势 ### 优点 - 语法简单与 Java,Ts,Swift 等语言十分相近,容易上手 - 开发成本 - 跨平台的主要优势在于代码逻辑的复用,减少各平台同一逻辑,因人而异的开发成本。 - 使用 skia 渲染 ui,跨平台开发不必考虑不同平台渲染上的差异 - 目前支持部署 Ios Android Web Linux 应用 - fuchsia os 指定 ui 开发语言 - 制作动画优秀,动画帧流畅、封装动画类思路清晰 ### 坑 - api 设计不稳定,之前版本更新对已有的 api 进行更改,导致会有一些依赖包出现问题 - 需要翻墙,不然安装升级体验极差 - 文字渲染功能不完善,部分情况会出现显示问题 ## fultter 动画 > 在任何系统的 UI 框架中,动画实现的原理都是相同的,即:在一段时间内,快速地多次改变 UI 外观;由于人眼会产生视觉暂留,所以最终看到的就是一个“连续”的动画,这和电影的原理是一样的。我们将 UI 的一次改变称为一个动画帧,对应一次屏幕刷新,而决定动画流畅度的一个重要指标就是帧率 FPS(Frame Per Second),即每秒的动画帧数。很明显,帧率越高则动画就会越流畅!一般情况下,对于人眼来说,动画帧率超过 16FPS,就比较流畅了,超过 32FPS 就会非常的细腻平滑,而超过 32FPS,人眼基本上就感受不到差别了。由于动画的每一帧都是要改变 UI 输出,所以在一个时间段内连续的改变 UI 输出是比较耗资源的,对设备的软硬件系统要求都较高,所以在 UI 系统中,动画的平均帧率是重要的性能指标,而在 Flutter 中,理想情况下是可以实现 60FPS 的,这和原生应用能达到的帧率是基本是持平的。 ### Flutter 中动画抽象 > 为了方便开发者创建动画,不同的 UI 系统对动画都进行了一些抽象,比如在 Android 中可以通过 XML 来描述一个动画然后设置给 View。Flutter 中也对动画进行了抽象,主要涉及 Animation、Curve、Controller、Tween 这四个角色 ### flutter 动画类型主要分为: 1. 隐式动画(自动更新)Animated 2. 显式动画(手动控制)Transition 3. 其他动画 ## 动画相关一些类 ### Animation > Animation 是一个抽象类,它本身和 UI 渲染没有任何关系,而它主要的功能是保存动画的插值和状态;其中一个比较常用的 Animation 类是 Animation。Animation 对象是一个在一段时间内依次生成一个区间(Tween)之间值的类。Animation 对象在整个动画执行过程中输出的值可以是线性的、曲线的、一个步进函数或者任何其他曲线函数等等,这由 Curve 来决定。 根据 Animation 对象的控制方式,动画可以正向运行(从起始状态开始,到终止状态结束),也可以反向运行,甚至可以在中间切换方向。Animation 还可以生成除 double 之外的其他类型值,如:Animation 或 Animation。在动画的每一帧中,我们可以通过 Animation 对象的 value 属性获取动画的当前状态值。 ### 隐式动画 ImplicitlyAnimatedWidget [(相关文档)](https://api.flutter-io.cn/flutter/widgets/ImplicitlyAnimatedWidget-class.html) > 隐式动画 子类一般取名为 Animated 开头 - TweenAnimationBuilder - AnimatedContainer - AnimatedSwitcher 组件切换 - AnimatedCrossFade 两组件切换 - AnimatedOpacity - AnimatedPadding - AnimatedAlign - AnimatedDefaultTextStyle - AnimatedPhysicalModel - AnimatedPositioned - AnimatedPositionedDirecional - AnimatedTheme - AnimatedSize - ... ### 显式动画 AnimatedWidget [(相关文档)](https://api.flutter-io.cn/flutter/widgets/AnimatedWidget-class.html) > 显式动画 子类一般取名为 Transition 结尾 - AnimatedBuilder,对于复杂的动画用例很有用,并且是 AnimatedWidget 子类的命名方案的显着例外。 - AlignTransition,这是 Align 的动画版本。 - DecoratedBoxTransition,这是一个动画版 DecoratedBox。 - PositionedTransition,这是一个动画版的 positioned。 - DefaultTextStyleTransition,这是一个动画版 DefaultTextStyle。 - RelativePositionedTransition,它是 Positioned 的动画版本 。 - RotationTransition,为小部件的旋转设置动画。 - ScaleTransition,它使小部件的比例动画化。 - SizeTransition,动画自己的大小。 - SlideTransition,它使小部件相对于其正常位置的位置动画化。 - FadeTransition,它是 Opacity 的动画版本。 - AnimatedModalBarrier,它是 ModalBarrier 的动画版本。 - ... ### 动画曲线 Curves [相关文档](https://api.flutter-io.cn/flutter/animation/Curves-class.html) > 动画过程可以是匀速的、匀加速的或者先加速后减速等。Flutter 中通过 Curve(曲线)来描述动画过程,我们把匀速动画称为线性的(Curves.linear),而非匀速动画称为非线性的。 我们可以通过 CurvedAnimation 来指定动画的曲线,如: - linear 匀速的 - decelerate 匀减速 - ease 开始加速,后面减速 - easeIn 开始慢,后面快 - easeOut 开始快,后面慢 - easeInOut 开始慢,然后加速,最后再减速 - ... > Transform - scale - rotale - translate ### 动画控制器 AnimationController [相关文档](https://api.flutter-io.cn/flutter/animation/AnimationController-class.html) > AnimationController 用于控制动画,它包含动画的启动 forward()、停止 stop() 、反向播放 reverse()等方法。AnimationController 会在动画的每一帧,就会生成一个新的值。默认情况下,AnimationController 在给定的时间段内线性的生成从 0.0 到 1.0(默认区间)的数字 - 构造器 - vsync, TickerProvider 动画帧通知 - duration, 动画时长 - reverseDuration, reverse 动画时长 - lowerBound = 0.0, 开始尺度 - upperBound = 1.0, 结束尺度 - debugLabel, - animationBehavior = AnimationBehavior.normal, - 方法 - forward - repeat - reset ### 帧更新通知 Ticker [相关文档](https://api.flutter-io.cn/flutter/scheduler/Ticker-class.html) > Flutter 应用在启动时都会绑定一个 SchedulerBinding,通过 SchedulerBinding 可以给每一次屏幕刷新添加回调,而 Ticker 就是通过 SchedulerBinding 来添加屏幕刷新回调,这样一来,每次屏幕刷新都会调用 TickerCallback。使用 Ticker(而不是 Timer)来驱动动画会防止屏幕外动画(动画的 UI 不在当前屏幕时,如锁屏时)消耗不必要的资源,因为 Flutter 中屏幕刷新时会通知到绑定的 SchedulerBinding,而 Ticker 是受 SchedulerBinding 驱动的,由于锁屏后屏幕会停止刷新,所以 Ticker 就不会再触发。 ### 动画范围 Tween [相关文档](https://api.flutter-io.cn/flutter/animation/Tween-class.html) > Tween 构造函数需要 begin 和 end 两个参数。Tween 的唯一职责就是定义从输入范围到输出范围的映射。输入范围通常为[0.0,1.0],但这不是必须的,我们可以自定义需要的范围。 > Tween 继承自 Animatable,而不是继承自 Animation,Animatable 中主要定义动画值的映射规则。 ### 绘制部件 CustomPaint [相关文档](https://api.flutter-io.cn/flutter/widgets/CustomPaint-class.html) > CustomPaint 本身没有动画属性,仅仅是绘制属性,一般情况下,CustomPaint 会和动画控制配合使用,达到理想的效果。 ## 使用动画制作素材工具(flare | rive), 制作动画 > 能够实现 Flutter 与现有动画工作流的深度集成. Rive 现已为多种层叠效果添加了支持, 例如投影, 内阴影, 光晕, 模糊和遮照. 目前 rive 2.0 版本能支持 web、flutter、c++、ios、android 上使用. 在 flutter 上使用 flare 需要安装 flare_flutter,flare 图像化工具新用户已经注册不了。 目前升级到了 2.0 版本更名为 rive, flutter 使用的包改为 Rive 下面是示例代码[点击跳转](https://gitee.com/django_tung/flutter-learning-experience/tree/master/lib/widget/flare) ## 动画实践示例 > 查看隐式动画实现源码会发现,实现方式和我们实现一个显式动画基本一致,可以理解为相当于在显式动画封装一层方便开发者使用。 使用隐式动画实现动画效果十分简单,开发者只需要定义好 Tween、Duration 两个角色就可以实现简单的动画效果。 这里有几个简单的隐式动画示例[点击跳转](https://gitee.com/django_tung/flutter-learning-experience/tree/master/lib/widget/animated) ```dart const TweenAnimationBuilder({ Key key, @required this.tween, @required Duration duration, Curve curve = Curves.linear, @required this.builder, VoidCallback onEnd, this.child, }) : assert(tween != null), assert(curve != null), assert(builder != null), super(key: key, duration: duration, curve: curve, onEnd: onEnd); ``` > 查看显式动画实现源码会发现,对比起显式动画来说简陋的多了。这就意味着开发者需要实现显式动画的代码量和自由度也相对应增多了。 ```dart const AnimatedBuilder({ Key key, @required Listenable animation, @required this.builder, this.child, }) : assert(animation != null), assert(builder != null), super(key: key, listenable: animation); ``` 实现一个显式动画需要开发者动手创建 Animation、Curve、Controller、Tween 这四个角色,用于控制动画流程。 这里有几个简单的显式动画示例[点击跳转](https://gitee.com/django_tung/flutter-learning-experience/tree/master/lib/widget/transition) > 使用 CustomPaint 实现动画[相关示例](https://gitee.com/django_tung/flutter-learning-experience/tree/release/v1.0/lib/widget/paint)