Android 动画机制

1. Android 中动画分类

  1. 逐帧动画;
  2. 补间动画;
  3. 属性动画;
  4. 过渡动画;

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 完成动画 
            ...
        }
    }
}

 

posted @ 2021-12-29 14:11  naray  阅读(307)  评论(0编辑  收藏  举报