Android动画总结

牧云@^-^@ 提交于 2020-02-14 06:04:00

目录

 

1.Android动画分几类

2.帧动画

2.1利用XML实现动画

2.1.1定义动画文件rocket_thrust.xml

2.1.2将AnimationDrawable设置为ImageView背景

2.1.3获取动画开始或停止

2.2利用Java代码实现动画

2.2.1生成帧动画

2.2.2动画开始或停止

3.补间动画

3.1XML配置

3.2Java代码实现动画

3.3自定义补间动画

4.属性动画

4.1属性动画与视图动画的区别

4.2属性动画介绍


1.Android动画分几类

1.1帧动画

1.2补间动画

1.3属性动画

2.帧动画

帧动画实现原理:接连加载一系列可绘制资源(图片)以创建动画,然后像一卷胶卷一样按顺序播放,利用人眼“视觉暂留”的原理,实现动画。

2.1利用XML实现动画

定义动画的 XML 文件位于 Android 项目的 res/drawable/ 目录中;

XML 文件包含一个 <animation-list> 元素(用作根节点)和一系列子 <item> 节点(每个节点定义一个帧):帧和帧时长的可绘制资源。以下是可绘制动画的 XML 文件示例:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="true">
        <item android:drawable="" android:duration="" />
    </animation-list>

通过将列表的 android:oneshot 属性设置为 true,此动画仅循环一次,然后便停止并保持在最后一帧。如果设置为 false,则动画会一直循环。

2.1.1定义动画文件rocket_thrust.xml

 <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="true">
        <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
        <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
        <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
        <item android:drawable="@drawable/rocket_thrust4" android:duration="200" />
        ......
    </animation-list>

2.1.2将AnimationDrawable设置为ImageView背景

<ImageView
        android:background="@drawable/rocket_thrust"
        android:id="@+id/rocket_image"
        />

2.1.3获取动画开始或停止

AnimationDrawable rocketAnimation;

    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
      rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
      rocketAnimation = (AnimationDrawable) rocketImage.getBackground();

      rocketImage.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {
            //开启动画
            //rocketAnimation.start();
            //停止动画
            //rocketAnimation.stop();
          }
      });
    }
    

2.2利用Java代码实现动画

2.2.1生成帧动画

AnimationDrawable  animationDrawable;
public void genAnimation(){
        //生成贞动画
        animationDrawable = new AnimationDrawable();
        for(int i=0; i<4; i++){
            int id = getResources().getIdentifier("rocket_thrust"+i,"drawable",getPackageName());
            Drawable drawable = getResources().getDrawable(id);
            animationDrawable.addFrame(drawable, 200);
        }
    }

2.2.2动画开始或停止

ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
//开始
public void start(View view){
        //设置执行一次
        animationDrawable.setOneShot(true);
        //设置动画背景
        rocketImage.setBackground(animationDrawable);
        // 特别注意:在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次
        animationDrawable.stop();
        //启动动画
        animationDrawable.start();
    }

//停止
    public void stop(View view){
        //设置执行一次
        animationDrawable.setOneShot(true);
        //设置动画背景
        rocketImage.setBackground(animationDrawable);
        //停止动画
        animationDrawable.stop();

    }

3.补间动画

Android提供了两种机制,您可以使用它们来创建简单的动画:补间动画,在该机制中,您告诉Android对视图的内容执行一系列简单的转换(位置、大小、旋转等);

和逐帧动画,它加载一系列可绘制的资源一个接一个。

在任何视图对象中都可以使用这两种动画类型来提供简单的旋转计时器、活动图标和其他有用的UI元素。补间动画处理这个包(android.view.animation);逐帧动画由AnimationDrawable类处理。

a.透明度-AlphaAnimation

b.旋转-RotateAnimation

c.缩放-ScaleAnimation

d.移动-TranslateAnimation

3.1XML配置

1)alpha:透明度变化,实现淡入淡出效果(数值范围0-1);

<alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="1000"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        />

android:fromAlpha:启动透明度

android:toAlpha:结束透明度

android:interpolator:插入器,控制动画执行速率;通过@android:anim找到系统提供的插入器;

2)rotate:控制物体旋转的动画。这个旋转发生在X-Y平面上。可以指定旋转中心使用的点,其中(0,0)是左上角的点。如果没有指定,(0,0)是默认的旋转点;

<rotate
        android:fromDegrees="0"
        android:toDegrees="60"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="10000"
        />

 android:fromDegrees:在动画开始时应用的旋转偏移量(偏移起始角度)

android:toDegrees:在动画结束时应用的旋转偏移量(偏移结束角度)

android:pivotX:被旋转对象所在点的X坐标,指定为一个绝对值,其中0为左边缘。

android:pivotY:被旋转对象所在点的Y坐标,指定为一个绝对值,其中0为左边缘。

3)scale:一种控制物体缩放大小的动画,您可以指定缩放中心使用的点;

<scale
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:toXScale="1.0"
        android:toYScale="1.0"
        android:pivotX="80%"
        android:pivotY="80%"
        android:duration="10000"
        />

android:fromXScale:X轴方向起始的缩放倍数;

android:fromYScale:Y轴方向起始的缩放倍数;

android:toXScale:X轴方向结束的缩放倍数;

android:toYScale:Y轴方向结束的缩放倍数;

android:pivotX:被旋转对象所在点的X坐标,指定为一个绝对值,其中0为左边缘。

android:pivotY:被旋转对象所在点的Y坐标,指定为一个绝对值,其中0为左边缘。

注意事项:pivot 这个属性主要是在translate 和 scale 动画中,这两种动画都牵扯到view 的“物理位置“发生变化,所以需要一个参考点。而pivotX和pivotY就共同决定了这个点;它的值可以是float或者是百分比数值。
以 pivotX 为例,说明其取不同的值的含义:
10:距离动画所在view自身左边缘10像素
10% :距离动画所在view自身左边缘 的距离是整个view宽度的10%
10%p:距离动画所在view父控件左边缘的距离是整个view宽度的10%

4)translate:控制动画位置移动;

<translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="500"
        android:toYDelta="100"
        android:duration="10000"
        />

android:fromXDelta:X轴视图移动开始的位置;

android:fromYDelta:Y轴视图移动开始的位置;

android:toXDelta:X轴视图移动结束的位置;

android:toYDelta:Y轴视图移动结束的位置;

5)加载XML动画,为视图(例如:ImageView)添加动画效果;

//加载动画资源
                Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
                //设置动画结束后保留结束状态
                animation.setFillAfter(true);
                //开始动画
                ImageView.startAnimation(animation);

3.2Java代码实现动画

1)AlphaAnimation

/**
         * android:fromAlpha:启动透明度(取值范围:0-1)
           android:toAlpha:结束透明度(取值范围:0-1)
         */
        Animation animation = new AlphaAnimation(0, 1);
        animation.setDuration(1000);
        //开始动画
        splashImg.startAnimation(animation);

2)RotateAnimation

     /**
         *
         * Constructor to use when building a RotateAnimation from code
         *
         * @param fromDegrees 旋转开始的角度,正值顺时针,负值逆时针
         *
         * @param toDegrees 旋转结束的角度,正值顺时针,负值逆时针
         *
         * @param pivotXType 指定如何相对点pivotXValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotXValue x水平方向缩放位置的参考点
         * @param pivotYType 指定如何相对点pivotYValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotYValue y垂直方向缩放位置的参考点
         *Type:Animation.ABSOLUTE:绝对,如果设置这种类型,后面pivotXValue取值就必须是像素点;比如:控件X方向上的中心点,pivotXValue的取值mIvScale.getWidth() / 2f
         *            Animation.RELATIVE_TO_SELF:相对于控件自己,设置这种类型,后面pivotXValue取值就会去拿这个取值是乘上控件本身的宽度;比如:控件X方向上的中心点,pivotXValue的取值0.5f
         *            Animation.RELATIVE_TO_PARENT:相对于它父容器(这个父容器是指包括这个这个做动画控件的外一层控件), 原理同上
         */
        Animation rotateAnimation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);

        //开始动画
        splashImg.startAnimation(rotateAnimation);

3)ScaleAnimation

/**
         * Constructor to use when building a ScaleAnimation from code
         *
         * @param fromX 动画在x水平方向上起始的缩放倍数
         * @param toX 动画在x水平方向上结束的缩放倍数
         * @param fromY 动画在y垂直方向上起始的缩放倍数
         * @param toY 动画在y垂直方向上结束的缩放倍数
         * @param pivotXType 指定如何相对点pivotXValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotXValue x水平方向缩放位置的参考点
         * @param pivotYType 指定如何相对点pivotYValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotYValue y垂直方向缩放位置的参考点
         *Type:Animation.ABSOLUTE:绝对,如果设置这种类型,后面pivotXValue取值就必须是像素点;比如:控件X方向上的中心点,pivotXValue的取值mIvScale.getWidth() / 2f
         *            Animation.RELATIVE_TO_SELF:相对于控件自己,设置这种类型,后面pivotXValue取值就会去拿这个取值是乘上控件本身的宽度;比如:控件X方向上的中心点,pivotXValue的取值0.5f
         *            Animation.RELATIVE_TO_PARENT:相对于它父容器(这个父容器是指包括这个这个做动画控件的外一层控件), 原理同上
         
         */
        Animation scaleAnimation = new ScaleAnimation(1,2,1,2,Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(1000);
        
        //开始动画
        splashImg.startAnimation(scaleAnimation);

4)TranslateAnimation

/**
         * Constructor to use when building a TranslateAnimation from code
         *
         * @param fromXDelta 开始的X轴位置
         * @param toXDelta   开始的Y轴位置
         * @param fromYDelta 结束的X轴位置
         * @param toYDelta   结束的Y轴位置
         */
        Animation translateAnimation = new TranslateAnimation(0, 0, 100, 100);

        //开始动画
        splashImg.startAnimation(translateAnimation);

5)动画集合使用

        //创建动画集合
        AnimationSet animationSet = new AnimationSet(true);
        // 特别说明以下情况
        // 因为在下面的旋转动画设置了无限循环(RepeatCount = INFINITE)
        // 所以动画不会结束,而是无限循环
        // 所以组合动画的下面两行设置是无效的
        animationSet.setRepeatMode(Animation.RESTART);
        animationSet.setRepeatCount(1);// 设置了循环一次,但无效

        //创建动画
        /**
         * android:fromAlpha:启动透明度(取值范围:0-1)
           android:toAlpha:结束透明度(取值范围:0-1)
         */
        Animation alpahAnimation = new AlphaAnimation(0, 1);
        alpahAnimation.setDuration(1000);
        alpahAnimation.setRepeatMode(Animation.RESTART);
        alpahAnimation.setRepeatCount(Animation.INFINITE);
        /**
         * Constructor to use when building a ScaleAnimation from code
         *
         * @param fromX 动画在x水平方向上起始的缩放倍数
         * @param toX 动画在x水平方向上结束的缩放倍数
         * @param fromY 动画在y垂直方向上起始的缩放倍数
         * @param toY 动画在y垂直方向上结束的缩放倍数
         * @param pivotXType 指定如何相对点pivotXValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotXValue x水平方向缩放位置的参考点
         * @param pivotYType 指定如何相对点pivotYValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotYValue y垂直方向缩放位置的参考点
         *Type:Animation.ABSOLUTE:绝对,如果设置这种类型,后面pivotXValue取值就必须是像素点;比如:控件X方向上的中心点,pivotXValue的取值mIvScale.getWidth() / 2f
         *            Animation.RELATIVE_TO_SELF:相对于控件自己,设置这种类型,后面pivotXValue取值就会去拿这个取值是乘上控件本身的宽度;比如:控件X方向上的中心点,pivotXValue的取值0.5f
         *            Animation.RELATIVE_TO_PARENT:相对于它父容器(这个父容器是指包括这个这个做动画控件的外一层控件), 原理同上
         */
        Animation scaleAnimation = new ScaleAnimation(1,2,1,2,Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(1000);

        /**
         *
         * Constructor to use when building a RotateAnimation from code
         *
         * @param fromDegrees 旋转开始的角度,正值顺时针,负值逆时针
         *
         * @param toDegrees 旋转结束的角度,正值顺时针,负值逆时针
         *
         * @param pivotXType 指定如何相对点pivotXValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotXValue x水平方向缩放位置的参考点
         * @param pivotYType 指定如何相对点pivotYValue模式。 三种模式如下:
         *        Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,或者
         *        Animation.RELATIVE_TO_PARENT;
         * @param pivotYValue y垂直方向缩放位置的参考点
         *Type:Animation.ABSOLUTE:绝对,如果设置这种类型,后面pivotXValue取值就必须是像素点;比如:控件X方向上的中心点,pivotXValue的取值mIvScale.getWidth() / 2f
         *            Animation.RELATIVE_TO_SELF:相对于控件自己,设置这种类型,后面pivotXValue取值就会去拿这个取值是乘上控件本身的宽度;比如:控件X方向上的中心点,pivotXValue的取值0.5f
         *            Animation.RELATIVE_TO_PARENT:相对于它父容器(这个父容器是指包括这个这个做动画控件的外一层控件), 原理同上
         */
        Animation rotateAnimation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);


        /**
         * Constructor to use when building a TranslateAnimation from code
         *
         * @param fromXDelta 开始的X轴位置
         * @param toXDelta   开始的Y轴位置
         * @param fromYDelta 结束的X轴位置
         * @param toYDelta   结束的Y轴位置
         */
        Animation translateAnimation = new TranslateAnimation(0, 0, 100, 100);


        animationSet.addAnimation(alpahAnimation);
        animationSet.addAnimation(rotateAnimation);
        animationSet.addAnimation(translateAnimation);
        animationSet.addAnimation(scaleAnimation);

        //开始动画
        splashImg.startAnimation(animationSet);

6)动画监听

为实现在某些动画开始或者结束时做一些额外操作可以监听动画状态,例如:动画直接完成进入主页;

animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                //动画开始
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //动画结束
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                //动画取消
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                //动画重复执行时
            }
        });
    }

3.3自定义补间动画

Android 提供了 Animation 作为补间动画抽象基类,而且为该抽象基类提供了 AlphaAnimation、RotationAnimation、ScaleAnimation、TranslateAnimation 四个实现类,这四个实现类只是补间动画的基本形式:透明度、旋转、缩放、位移。但是要实现复杂的动画,就需要继承 Animation。继承 Animation 类关键是要重写一个方法:

applyTransformation(float interpolatedTime,Transformation t)
interploatedTime: 代表了动画的时间进行比。不管动画实际的持续时间如何,当动画播放时,该参数总是从 0 到 1。
Transformation t:该参数代表了补间动画在不同时刻对图形或组件的变形程度。

在实现自定义动画的关键就是重写 applyTransformation 方法时 根据 interpolatedTime 时间来动态地计算动画对图片或视图的变形程度。

Transformation 代表了对图片或者视图的变形,该对象封装了一个 Matrix 对象,对它所包装了 Matrix 进行位移、倾斜、旋转等变换时,Transformation 将会控制对应的图片或视图进行相应的变换。

为了控制图片或者 View 进行三维空间的变换,还需要借助于 Android 提供的一个 Camera,这个 Camera 并非代表手机摄像头,而是空间变换工具。作用类似于 Matrix,其常用方法如下:
getMatrix(Matrix matrix):将 Camera 所做的变换应用到指定的 matrix 上。
rotateX(float deg):将组件沿 X 轴旋转。
rotateY(float deg):将组件沿 Y 轴旋转。
rotateZ(float deg):将组件沿 Z 轴旋转。
translate(float x,float y,float z):目标组件在三维空间里变换。
applyToCanvas(Canvas canvas):把 Camera 所做的变换应用到 Canvas 上。

下面示例利用 Camera 自定义三维空间动画。
自定义 Animation

package com.github.baby.owspace.view.activity;

import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;

/**
 * 自定义补间动画
 */

public class CustomAnimation extends Animation {

    private float centerX;
    private float centerY;

    //定义动画持续时间
    private int duration;
    /**
     * Camera实例可用于计算3D转换并生成可应用的矩阵(Matrix),例如可应用于
     {@link Canvas}。
     */
    private Camera camera = new Camera();

    public CustomAnimation(float x, float y, int duration){
        this.centerX = x;
        this.centerY = y;
        this.duration = duration;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        //设置动画执行的时间
        setDuration(duration);
        //设置动画结束保留效果
        setFillAfter(true);
        setInterpolator(new LinearInterpolator());
    }

    /**
     * public boolean getTransformation(long currentTime, Transformation outTransformation) {
     *     applyTransformation(float interpolatedTime, Transformation t)
     * }
     * 帮助getTransformation方法应用具体的转换(动画)。Animation子类应该实现这applyTransformation方法,
     * 从而应用它们的转换(动画),给它们一个插值。此方法的实现应该始终替换它们正在以其他方式执行的指定转换(动画)。
     *
     * @param interpolatedTime 经过插值函数后的归一化时间值(0.0到1.0),代表了动画的时间进行比。
     *                         不管动画实际的持续时间如何,当动画播放时,该参数总是从 0 到 1。
     * @param t 具体执行转换对象(动画),该参数代表了补间动画在不同时刻对图形或组件的变形程度;
     *
     *          Transformation 代表了对图片或者视图的变形,该对象封装了一个 Matrix 对象,对它所包装了 Matrix 进行位移、倾斜、旋转等变换时,
     *          Transformation 将会控制对应的图片或视图进行相应的变换。
     */

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        //super.applyTransformation(interpolatedTime, t);
        camera.save();
        //根据interpolatedTime时间控制X,Y,Z上偏移
        camera.translate(100.0f - 100.0f*interpolatedTime,150.0f * interpolatedTime - 150,80.0f - 80.0f * interpolatedTime);
        //根据interpolatedTime时间设置X轴和Y轴旋转
        camera.rotateX(360*interpolatedTime);
        camera.rotateY(360*interpolatedTime);
        //获取Transformation参数的Matrix对象
        Matrix matrix = t.getMatrix();
        camera.getMatrix(matrix);
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
        camera.restore();
    }
}

具体使用

splashImg.startAnimation(new CustomAnimation(splashImg.getMeasuredWidth(), 
splashImg.getMeasuredHeight(), 5000));

4.属性动画

4.1属性动画与视图动画的区别

视图动画系统仅提供为 View 对象添加动画效果的功能,因此,如果您想为非 对象添加动画效果,则必须实现自己的代码才能做到。视图动画系统也存在一些限制,因为它仅公开 对象的部分方面来供您添加动画效果;例如,您可以对视图的缩放和旋转添加动画效果,但无法对背景颜色这样做。

视图动画系统的另一个缺点是它只会在绘制视图的位置进行修改,而不会修改实际的视图本身。例如,如果您为某个按钮添加了动画效果,使其可以在屏幕上移动,该按钮会正确绘制,但能够点击按钮的实际位置并不会更改,因此您必须通过实现自己的逻辑来处理此事件。

有了属性动画系统,您就可以完全摆脱这些束缚,还可以为任何对象(视图和非视图)的任何属性添加动画效果,并且实际修改的是对象本身。属性动画系统在执行动画方面也更为强健。概括地讲,您可以为要添加动画效果的属性(例如颜色、位置或大小)分配 Animator,还可以定义动画的各个方面,例如多个 Animator 的插值和同步。

不过,视图动画系统的设置需要的时间较短,需要编写的代码也较少。如果视图动画可以完成您需要执行的所有操作,或者现有代码已按照您需要的方式运行,则无需使用属性动画系统。在某些用例中,也可以针对不同的情况同时使用这两种动画系统。

4.2属性动画介绍

属性动画系统是一个强健的框架,用于为几乎任何内容添加动画效果。您可以定义一个随时间更改任何对象属性的动画,无论其是否绘制到屏幕上。属性动画会在指定时长内更改属性(对象中的字段)的值。要添加动画效果,请指定要添加动画效果的对象属性,例如对象在屏幕上的位置、动画效果持续多长时间以及要在哪些值之间添加动画效果。

借助属性动画系统,您可以定义动画的以下特性:

android:duration,时长:您可以指定动画的时长。默认时长为 300 毫秒。
android:interploator,时间插值:您可以指定如何根据动画的当前已播放时长来计算属性的值。
android:repeatCount ,重复计数和行为:您可以指定是否在某个时长结束后重复播放动画以及重复播放动画多少次。您还可以指定是否要反向播放动画。如果将其设置为反向播放,则会先播放动画,然后反向播放动画,直到达到重复次数。
<set .../> ,Animator 集:您可以将动画分成多个逻辑集,它们可以一起播放、按顺序播放或者在指定的延迟时间后播放。
帧刷新延迟:您可以指定动画帧的刷新频率。默认设置为每 10 毫秒刷新一次,但应用刷新帧的速度最终取决于整个系统的繁忙程度以及系统为底层计时器提供服务的速度。

1)API 概览

您可以在 android.animation 中找到属性动画系统的大多数 API。

Animator 类提供了创建动画的基本结构。您通常不会直接使用此类,因为它只提供极少的功能,这些功能必须经过扩展才能全面支持为值添加动画效果。以下子类可扩展 Animator:

a.Animator 类提供了创建动画的基本结构。

b.ValueAnimator:属性动画的主计时引擎,它也可计算要添加动画效果的属性的值。它具有计算动画值所需的所有核心功能,同时包含每个动画的计时详情、有关动画是否重复播放的信息、用于接收更新事件的监听器以及设置待评估自定义类型的功能。

c.ObjectAnimator:ValueAnimator 的子类,用于设置目标对象和对象属性以添加动画效果。此类会在计算出动画的新值后相应地更新属性。在大多数情况下,您不妨使用 ObjectAnimator,因为它可以极大地简化对目标对象的值添加动画效果这一过程。不过,有时您需要直接使用 ValueAnimator,因为 ObjectAnimator 存在其他一些限制,例如要求目标对象具有特定的访问器方法。

d.AnimatorSet:此类提供一种将动画分组在一起的机制,以使它们彼此相对运行。

2)时间插值器

时间插值器指定了如何根据时间计算动画中的特定值。例如,您可以指定动画在整个动画中以线性方式播放,即动画在整个播放期间匀速移动;也可以指定动画使用非线性时间,例如动画在开始后加速并在结束前减速。

IntEvaluator    这是用于计算 int 属性的值的默认评估程序。
FloatEvaluator    这是用于计算 float 属性的值的默认评估程序。
ArgbEvaluator    这是用于计算颜色属性的值(用十六进制值表示)的默认评估程序。
TypeEvaluator    此接口用于创建您自己的评估程序。如果您要添加动画效果的对象属性不是 int、float 或颜色,那么您必须实现 TypeEvaluator 接口,才能指定如何计算对象属性添加动画效果之后的值。如果您想以不同于默认行为的方式处理 int、float和颜色,您还可以为这些类型的值指定自定义 TypeEvaluator。如需详细了解如何编写自定义评估程序,请参阅使用 TypeEvaluator 部分。

3)使用ValueAnimator添加动画的步骤

 ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
    animation.setDuration(1000);
    animation.start();

a.借助 ValueAnimator 类,您可以为动画播放期间某些类型的值添加动画效果,只需指定一组要添加动画效果的 int、float 或颜色值即可。您可以通过调用 ValueAnimator 的任一工厂方法来获取它:ofInt()、ofFloat() 或 ofObject()。

b.设置动画执行时间;

c.动画启动;

d.您可以通过向 ValueAnimator 对象添加 AnimatorUpdateListener 来使用动画的值

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator updatedAnimation) {
            // You can use the animated value in a property that uses the
            // same type as the animation. In this case, you can use the
            // float value in the translationX property.
            float animatedValue = (float)updatedAnimation.getAnimatedValue();
            textView.setTranslationX(animatedValue);
        }
    });

在 onAnimationUpdate() 方法中,您可以访问更新后的动画值,并将其用在您的某个视图的属性中。

3)动画使用的一般步骤

属性动画的一般使用:

定义属性动画和补间动画等类似,有两种方式:

a.使用 ValueAnimator 或者 ObjectAnimator 的静态工厂方法创建动画。
b.使用资源文件来定义动画。
属性动画的使用:

a.创建 ValueAnimator 或 ObjectAnimator 对象 —— 即可以从 XML 资源文件加载该动画也可以直接调用 ValueAnimator 或者 ObjectAnimator 的静态工厂方法创建动画。
b.根据需要为 Animator 对象设置属性。
c.如果需要监听 Animator 的动画开始事件,动画结束事件、动画重复事件、动画值改变事件,并根据事件提供响应处理代码,需要为Animator 对象设置监听器。
d.如果有多个动画需要同时播放,需要使用 AnimatorSet 组合这些动画。
e.调用 Animator 对象的 start 启动动画。

4)属性动画示例:
a.布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:id="@+id/imageView_b"
        android:src="@drawable/img"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
    <ImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:id="@+id/imageView_c"
        android:src="@drawable/img"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

b.实现具体动画

public class PropertyAnimator  extends Activity implements View.OnClickListener {

    private int[] mRes = {R.id.imageView_a, R.id.imageView_b};
    private List<ImageView> mImageViews = new ArrayList<>();
    private boolean mFlag = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.property_animator);

        int sum = mRes.length;
        for (int i = 0; i < sum; i++) {
            ImageView imageView = (ImageView) findViewById(mRes[i]);
            imageView.setOnClickListener(this);
            mImageViews.add(imageView);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageView_a:
                if (mFlag) {
                    startAnim();
                } else {
                    closeAnim();
                }
                break;
            case R.id.imageView_b:
                Toast.makeText(PropertyAnimator.this, "b", Toast.LENGTH_SHORT).show();
                break;
        }
    }

    private void closeAnim() {
        ObjectAnimator animator0 = ObjectAnimator.ofFloat(mImageViews.get(0),
                "alpha", 0.5F, 1F);
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(mImageViews.get(1),
                "translationY", 200F, 0);
        AnimatorSet set = new AnimatorSet();
        set.setDuration(500);
        set.setInterpolator(new BounceInterpolator());
        set.playTogether(animator0, animator1, animator2, animator3, animator4);
        set.stop();
        mFlag = true;
    }

    private void startAnim() {
        ObjectAnimator animator0 = ObjectAnimator.ofFloat(
                mImageViews.get(0),
                "alpha",
                1F,
                0.5F);
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(
                mImageViews.get(1),
                "translationY",
                200F);
        AnimatorSet set = new AnimatorSet();
        set.setDuration(500);
        set.setInterpolator(new BounceInterpolator());
        set.playTogether(
                animator0,
                animator1
);
        set.start();
        mFlag = false;
    }
}

参考:

https://developer.android.google.cn/guide/topics/graphics/prop-animation?hl=Language#value-animator

https://www.jianshu.com/p/609b6d88798d

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!