zoukankan      html  css  js  c++  java
  • 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 完成动画 
                ...
            }
        }
    }
  • 相关阅读:
    ylbtech-dbs-m-QQ邮箱
    ylbtech-Bill(发票管理)-数据库设计
    ylbtech-Recode(记录)-数据库设计
    ylbtech-LanguageSamples-Yield
    ylbtech-LanguageSamples-XMLdoc
    ylbtech-LanguageSamples-Versioning(版本控制)
    线程局部变量的使用
    守护线程的创建和运行
    有助于改善性能的技巧
    使用NIO提升性能
  • 原文地址:https://www.cnblogs.com/naray/p/13114545.html
Copyright © 2011-2022 走看看