6.Android动画
Android动画
原理:不停修改view的不同属性,刷新
动画实现方式
GIf
一般Gif或者帧动画 的性能差是由于图过多,每秒种几十帧,每一帧都是一张图。一个小动画往往需要几十张图。如果变成资源下载,资源包体积难以控制。
原生
Native 动画是属性动画或者补间动画。性能相比较gif而言性能比较好,但是有大量动画的需求时,往往生产力是不够的,一开始手动码动画,一个动画最多时写了3000多行code。
Native 动画优缺点:
开发成本高
必须发版
不能完全100%还原复杂动画,调参数比较繁
图片资源大,影响apk包大小
SVG
SVG图片格式,一种矢量图形。另一个角度来讲一张图或者一个动画,是由很多上下层级的图层构成。比如当前的简单的图,看到的是一张图,但在设计工具中是三个图层构成,有着不同的上下层级顺序。
原理:通过设置帧率,来生成一个配置文件,使得每一帧都有一个配置,每一帧都是关键帧,通过帧率去刷每一帧的画面,这个思路跟gif很像,但是通过配置使得动画过程中图片都可以得到复用。性能就提升上来了。
Lottie
完全按照设计工具的设计思路来进行还原,将动画脚本导出并解析。动画脚本非常的轻量。将所有的动画拆成多个层级,每个层级layer都有一个动画配置,播放时解析多个layer的配置,并给每个layer做相应的动画。也达到了图片可以复用。当需要解析高阶插值(二次线性方程,贝塞尔曲线方程)时,性能相对而言差一点。
Lottie使用注意
都是canvas 画布操作
lottie动画很卡顿,不流畅//硬件加速,开启之后瞬间丝滑
遮罩或者蒙版,性能将会受到影响。
如果你在一个列表中使用动画, 我们建议你配置 LottieAnimationView.setAnimation(String, CacheStrategy) 的第二个参数——缓存策略,这样动画就不必每次都反序列化。
Android中的动画
三种:补间动画、帧动画、属性动画。
补间动画是放置到res/anim/下面
帧动画是放置到res/drawable/下面,子节点为animation-list,在这里定义要显示的图片和每张图片的显示时长
上下左右浮动效果
1 | |
帧动画
传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影,一张张图片不断的切换,形成动画效果,要自己指定每一帧。
帧动画使用xml定义
在drawable目录下定义xml文件,子节点为animation-list,在这里定义要显示的图片和每张图片的显示时长1
2
3
4
5<animation-list xmlns:androandroid:oneshot="false">
<item android:drawable="@drawable/g1" android:duration="200" />
<item android:drawable="@drawable/g2" android:duration="200" />
<item android:drawable="@drawable/g3" android:duration="200" />
</animation-list>在屏幕上播放帧动画
1
2
3
4
5
6ImageView iv = (ImageView) findViewById(R.id.iv);
//把动画文件设置为imageView的背景
iv.setBackgroundResource(R.drawable.animations);
AnimationDrawable ad = (AnimationDrawable) iv.getBackground();
//播放动画
ad.start();
补间动画
- 如果动画中的图像变换比较有规律时,例如图像的移动(TranslateAnimation)、旋转(RotateAnimation)、缩放(ScaleAnimation)、透明度渐变(AlphaAnimation),这些图像变化过程中的图像都可以根据一定的算法自动生成,我们只需要指定动画的第一帧和最后一帧图像即可,这种自动生成中间图像的动画就是补间动画。
- 补间动画,只是一个动画效果,组件其实还在原来的位置上,xy没有改变
属性动画
- 补间动画改变了View的显示效果而已,而不会真正去改变View的属性,比如说,屏幕的左上角有一个按钮,然后通过补间动画将它移动到了屏幕的右下角,现在去尝试点击这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。
- 动画的对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性值被实实在在的改变了。
ViewPropertyAnimator
使⽤ View.animate() 创建对象,以及使⽤ViewPropertyAnimator.translationX() 等⽅法来设置动画;
可以连续调⽤来设置多个动画;
可以⽤ setDuration() 来设置持续时间;
可以⽤ setStartDelay() 来设置开始延时;
以及其他⼀些便捷⽅法。
view.animate().translationX(500);
ValueAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,是一个非常重要的类。
可以在动画多的时候用
1 | |
ObjectAnimator
相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。 它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。
1 | |
属性动画的优势在于,可以为⾃定义属性设置动画。
1 | |
另外,⾃定义属性需要设置 getter 和 setter ⽅法,并且 setter ⽅法⾥需要调⽤invalidate() 来触发重绘:
1 | |
设置旋转起点
1 | |
可以使用reverse,就不需要重新创建个动画了
Interpolator
插值器,⽤于设置时间完成度到动画完成度的计算公式,直⽩地说即设置动画的速度曲线,通过 setInterpolator(Interpolator) ⽅法来设置。常⽤的有 AccelerateDecelerateInterpolator、
AccelerateInterpolator、DecelerateInterpolator、LinearInterpolator 。
差值器和估值器是什么?
Interpolator 负责控制动画变化的速率,使得基本动画能够以匀速、加速、减速、抛物线速率等各种速率变化。
TypeEvaluator 设置属性值,从初始值过度到结束值的变化具体数值。
PropertyValuesHolder
⽤于设置更加详细的动画,例如多个属性应⽤于同⼀个对象:
1 | |
或者,配合使⽤ Keyframe ,对⼀个属性分多个段:
1 | |
AnimatorSet
将多个 Animator 合并在⼀起使⽤,先后顺序或并列顺序都可以:
1 | |
TypeEvaluator
⽤于设置动画完成度到属性具体值的计算公式。默认的 ofInt() ofFloat() 已经有了⾃带的 IntEvaluator FloatEvaluator ,但有的时候需要⾃⼰设置Evaluator。例如,对于颜⾊,需要为 int 类型的颜⾊设置 ArgbEvaluator,⽽不是让它们使⽤ IntEvaluator
1 | |
如果你对 ArgbEvaluator 的效果不满意,也可以⾃⼰写⼀个 HsvEvaluator :
1 | |
另外,对于不⽀持的类型,也可以使⽤ ofObject() 来在创建 Animator 的同时就设置上 Evaluator,⽐如 NameEvaluator :
1 | |
硬件加速
硬件加速是什么
使⽤ CPU 绘制到 Bitmap,然后把 Bitmap 贴到屏幕,就是软件绘制;
使⽤ CPU 把绘制内容转换成 GPU 操作,交给 GPU,由 GPU 负责真正的绘制,就叫硬件绘制;
使⽤ GPU 绘制就叫做硬件加速
怎么就加速了?
GPU 分摊了⼯作
GPU 绘制简单图形(例如⽅形、圆形、直线)在硬件设计上具有先天优势,会更快流程得到优化(重绘流程涉及的内容更少)
硬件加速的缺陷:
兼容性。由于使⽤ GPU 的绘制(暂时)⽆法完成某些绘制,因此对于⼀些特定的API,需要关闭硬件加速来转回到使⽤ CPU 进⾏绘制。
view动画的特殊使用场景
activity overridePendingTransition,可以是补间(下面的),也可以是熟悉动画
FragmentTransaction中的 setCustomAnimations 方法(不能是属性动画)

