Android 动画机制
1. Android 中动画分类
- 逐帧动画;
- 补间动画;
- 属性动画;
- 过渡动画;
2. 动画机制
1. 逐帧动画
逐帧动画也叫Drawable Animation,在Android中逐帧动画实现是通过将动画素材按帧渲染,就是开发可以指定每帧动画的图片和持续时间。
2. 补间动画
与逐帧动画不同,补间动画不需要设置动画过程中的每一帧,只需要设置动画的开始与结束两个关键帧,并指定动画的变化时间和方式等,然后将由Android系统进行计算,通过给开始与结束插入渐变值写成动画的平滑过度,从而对View的内容完成一系列的图形变换来实现动画效果。主要有四种效果:1. 透明度动画效果;2. 缩放动画效果;3. 平移动画效果;4. 旋转动画效果;
补间动画开始与结束两个关键帧插入的渐变值,就是通过插值器(Interpolator)完成的。
在补间动画中,完成的动画效果中通过改变View的绘制效果,并未改变View属性值。
3. 属性动画
1. 什么是属性动画?
属性动画是Android 3.0引入的,相当于补间动画的升级版,补间动画是通过改变View的绘制完成动画效果的,并未改变View的属性值。
属性动画则是通过改变View的属性值来完成动画效果的,比如:透明度、缩放、平移、旋转动画效果都是通过改变View属性值完成的。并且属性动画几乎可以对任何对象执行动画,并不限制于View。
补间动画与属性动画的区别:
补间动画与属性动画都设置动画的开始与结束两个关键帧,但是,补间动画通过改变View的绘制过程完成动画,而View属性不变。而属性动画是通过直接改变View的属性值完成动画效果,并且属性动画可以对任何对象执行动画。
2. 属性动画实现
属性动画的基类是Animator,它是一个抽象类,不会直接使用它,通过继承Animator基类并实现其中一些关键方法。Android中已经为开发者提供了一些属性动画子类。
首先介绍一个概念Evaluator,它不是Animator的子类,Evaluator是用来控制属性动画如何计算属性值的。源码如下:
/** * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators * allow developers to create animations on arbitrary property types, by allowing them to supply * custom evaluators for types that are not automatically understood and used by the animation * system. * * @see ValueAnimator#setEvaluator(TypeEvaluator) */ public interface TypeEvaluator<T> { /** * This function returns the result of linearly interpolating the start and end values, with * <code>fraction</code> representing the proportion between the start and end values. The * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>, * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>, * and <code>t</code> is <code>fraction</code>. * * @param fraction The fraction from the starting to the ending values * @param startValue The start value. * @param endValue The end value. * @return A linear interpolation between the start and end values, given the * <code>fraction</code> parameter. */ public T evaluate(float fraction, T startValue, T endValue); }
属性动画子类:
1. AnimatorSet
AnimatorSet是Animator子类,用来组合多个Animator,AnimatorSet控制Animator是顺序播放还是同时播放。
2. ValueAnimator
ValueAnimator是属性动画最重要的一个类,继承自Animator。它定义了属性动画大部分的核心功能,包括计算各个帧的属性值、处理更新事件、按照属性值的类型控制计算规则等。
一个完整的属性动画由以下两部分组成:
1. 计算动画各个帧的相关属性值;
2. 将这些属性值设置给指定的对象;
而ValueAnimator完成了第一部分功能,第二部分功能需要开发都自己实现完成。
3. ObjectAnimator
ObjectAnimator属性动画继承自ValueAnimator类,封闭实现了ValueAnimator的第二部分功能。
4. 过渡动画
过渡动画是Android 4.4引入的新框架,它的本质还是属性动画,只不过是对属性动画进行了封装。作用就是实现了Activity或者View的过渡动画效果。与属性动画相比,过渡动画的动画前后准备不同布局。比如:点击一个View在屏幕中间位置放大显示View。或者Activity/Fragment的切换效果等。
5. 非主线程渲染动画
SurfaceView与TextureView对比,TextureView可以移动、旋转、缩放、设置透明,但占用内存也比SurfaceView多。
SurfaceView使用子线程渲染动画
SurfaceView源码:
/** * Mock version of the SurfaceView. * Only non override public methods from the real SurfaceView have been added in there. * Methods that take an unknown class as parameter or as return object, have been removed for now. * * TODO: generate automatically. * */ public class SurfaceView extends MockView { public SurfaceView(Context context) { this(context, null); } public SurfaceView(Context context, AttributeSet attrs) { this(context, attrs , 0); } public SurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public boolean gatherTransparentRegion(Region region) { return false; } public void setZOrderMediaOverlay(boolean isMediaOverlay) { } public void setZOrderOnTop(boolean onTop) { } public void setSecure(boolean isSecure) { } public SurfaceHolder getHolder() { return mSurfaceHolder; } private SurfaceHolder mSurfaceHolder = new SurfaceHolder() { @Override public boolean isCreating() { return false; } @Override public void addCallback(Callback callback) { } @Override public void removeCallback(Callback callback) { } @Override public void setFixedSize(int width, int height) { } @Override public void setSizeFromLayout() { } @Override public void setFormat(int format) { } @Override public void setType(int type) { } @Override public void setKeepScreenOn(boolean screenOn) { } @Override public Canvas lockCanvas() { return null; } @Override public Canvas lockCanvas(Rect dirty) { return null; } @Override public void unlockCanvasAndPost(Canvas canvas) { } @Override public Surface getSurface() { return null; } @Override public Rect getSurfaceFrame() { return null; } }; }
通过lockCanvas()获取Canvas实例,创建子线程并进行绘制,通过unlockCanvasAndPost()方法,通过渲染引擎渲染。
示例:
public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mSurfaceHolder; private Canvas mCanvas; ... class UpdateViewThread extends Thread { @Override public void run() { //防止是获取不到Canvas SurfaceHolder surfaceHolder = mSurfaceHolder; // 锁定画布 synchronized (surfaceHolder) { if (surfaceHolder != null) { mCanvas = surfaceHolder.lockCanvas(); if (mCanvas == null) { return; } } } // TODO: 2020/6/24 完成动画 ... } } }