Android三大动画使用总结

动画在Android开发中比较常用,主要有:帧动画、补间动画、属性动画(3.0增加),下面开始学习:

一、Frame Animation


1、简介

Frame Animation,逐帧动画是一种常见的动画形式,其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。

简单理解:
连续播放准备好的关键帧图片,形成动画

2、xml实现

先创建帧动画文件

// res/drawable/anim_frame.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <!-- 帧动画
         以 animation-list 为根节点
         oneshot : 是否只播放一次
         duration : 每张图片持续时间
     -->
    <item
        android:drawable="@drawable/smoke1"
        android:duration="200"/>
    <item
        android:drawable="@drawable/smoke2"
        android:duration="200"/>
        
    …… 其余item省略
</animation-list>

设置动画

// 2. 将动画设置给 iv,二选一
    // 2.1 设置成图片资源
    mIv.setImageResource(R.drawable.anim_frame);

    // 2.2 设置成背景资源,如果单纯想显示动画,就把src图片去掉,否则就是图片会盖在动图上面,因为是背景
    // mIv.setBackgroundResource(R.drawable.anim_frame);

// 3. 获取动画,根据设置动画方式,二选一
    // 3.1 设置为图片资源的获取方式
    mAnimDrawable = (AnimationDrawable) mIv.getDrawable();
    
    // 3.2 设置为背景资源的获取方式
    // mAnimDrawable2 = (AnimationDrawable) mIv.getBackground();

// 4. 也可在代码中设置 是否播放一次
mAnimDrawable.setOneShot(false);

/**
 * 开始动画
 * @param view
 */
public void startAnim(View view) {
    mAnimDrawable.start();
}

/**
 * 停止动画
 * @param view
 */
public void stopAnim(View view) {
    mAnimDrawable.stop();
}

3、代码实现

// 1. 创建 AnimationDrawable 对象
mAnimDrawable = new AnimationDrawable();

// 2. 设置是否播放一次
mAnimDrawable.setOneShot(false);

// 3. 添加帧
for (int i = 1; i < 23; i++) {
    int id = getResources().getIdentifier("smoke" + i, "drawable", getPackageName());
    Drawable drawable = ContextCompat.getDrawable(this, id);
    // 添加帧图片,并设置每帧持续时间
    mAnimDrawable.addFrame(drawable, 200);
}

// 4. iv 设置动画对象
    // 4.1 设置为图片资源
    mIv.setImageDrawable(mAnimDrawable);
    // 4.2 设置为背景资源
    // mIv.setBackgroundDrawable(mAnimDrawable);

/**
 * 开始动画
 * @param view
 */
public void startAnim(View view) {
    mAnimDrawable.start();
}

/**
 * 停止动画
 * @param view
 */
public void stopAnim(View view) {
    mAnimDrawable.stop();
}

效果图:

4、要点

  1. 帧动画主要使用AnimationDrawable对象
  1. 作用对象:view
  2. 本质:播放事先准备好的一张张图片
  3. stop()停止在当前帧,已经停止调用无效果
  4. start()从第一帧开始播放,正在播放调用无效果
  5. 设置为图片资源,自动播放;设置为背景资源,需手动播放
  6. 避免使用较大的图片而引起OOM

你可能需要的:在线GIF分解

二、Tween Animation


1、简介

Tween Animation,补间动画指的是做flash动画时,在两个关键帧中间需要做“补间动画”,才能实现图画的运动;插入补间动画两个关键帧后,之间的插补帧是由计算机自动运算而得到的。

简单理解:
需要定义开始与结束两个关键帧,指定好运动的方式与时间,系统就会自动计算加入中间帧进行播放,形成动画

2、分类和属性

分类:

xml 标签 java 对象 功能
alph AlphaAnimation 透明度动画
rotate RotateAnimation 旋转动画
translate TranslateAnimation 位移动画
scale ScaleAnimation 缩放动画
set AnimationSet 补间动画集合

属性:

xml 属性 功能 可用于动画
duration 动画持续时间 ALL
startOffset 动画开始延迟时间 ALL
fillBefore 动画完成后,保持动画前状态,默认true ALL
fillAfter 动画完成后,保持动画后状态,默认false ALL
fillEnabled 是否使用fillBefore值,对fillAfter值无影响,默认为true ALL
repeatMode 重放,restart正序重放,reverse倒序回放,默认restart ALL
repeatCount 重放次数,播放次数=重放次数+1,infinite为无限播放 ALL(set使用无效)
interpolator 插值器 ALL
fromAlpha 开始时透明图(0.0~1.0) Alpha
toAlpha 结束时透明图(0.0~1.0) Alpha
fromDegrees 开始时角度 Rotate
toDegrees 结束时角度 Rotate
fromXDelta 动画起始x轴位置 Translate
toXDelta 动画结束x轴位置 Translate
fromYDelta 动画起始y轴位置 Translate
toYDelta 动画结束y轴位置 Translate
fromXScale 开始x轴方向缩放值 Scale
toXScale 结束时x轴方向缩放值 Scale
fromYScale 开始y轴方向缩放值 Scale
toYScale 开始y轴方向缩放值 Scale
pivotX 旋转、缩放中心点x坐标 Rotate、Scale
pivotY 旋转、缩放中心点y坐标 Rotate、Scale
shareInterpolator 共享插值器 Set

注意:

通过Xml创建动画时

1、位置变化相关属性

取值类型为:float, fraction 的属性,需要注意:

  • 设置为数字时(如50,0.5),轴点为View的左上角的原点在x方向和y方向加上50px的点。在Java代码里面设置这个参数的对应参数是Animation.ABSOLUTE

  • 设置为百分比时(如50%),轴点为View的左上角的原点在x方向加上自身宽度50%和y方向自身高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_SELF

  • 设置为百分比p时(如50%p),轴点为View的左上角的原点在x方向加上父控件宽度50%和y方向父控件高度50%的点。在Java代码里面设置这个参数的对应参数Animation.RELATIVE_TO_PARENT

2、缩放相关属性

取值类型为dimension, float, fraction的属性 ,需要注意:

  • dimension:如50dp,表示view的x轴(宽)或y轴(高)为50dp

  • float、百分比:如0.5、50%,同等效果,表示View当前宽高为原大小的50%

  • 百分比p:如50%p,表示View当前宽高为父容器的50%

查看属性取值类型:点击属性使属性获取焦点,鼠标悬浮在属性上等待一会即可。

如果没有,可参考Android studio 3.1 基础设置 > 快速文档设置

3、AlphaAnimation

透明度动画

  • xml实现 (在res/anim下创建)
// 1. 创建动画文件
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1.0"
    android:toAlpha="0.2"

    android:duration="500"
    android:startOffset="500"
    android:fillAfter="false"
    android:repeatMode="restart"
    android:repeatCount="1"
    android:interpolator="@android:anim/linear_interpolator">
</alpha>

// 2. 加载动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha_sample);

// 3. 设置动画作用对象并开始动画播放
mView.startAnimation(animation);
  • java实现
// 1. 创建动画,并设置相关属性
AlphaAnimation animation = new AlphaAnimation(1.0f,0.2f);
animation.setDuration(500);
animation.setStartOffset(500);
animation.setFillAfter(false);
animation.setRepeatCount(1);
animation.setRepeatMode(Animation.RESTART);
animation.setInterpolator(new AccelerateDecelerateInterpolator());

// 2. 设置动画作用对象并开始动画播放
mView.startAnimation(animation);

4、RotateAnimation

旋转动画

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"

    android:duration="500"
    android:startOffset="500"
    android:fillAfter="false"
    android:repeatMode="restart"
    android:repeatCount="1"
    android:interpolator="@android:anim/accelerate_interpolator">

</rotate>

5、TranslateAnimation

位移动画

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="-30%p"
    android:toXDelta="30%p"
    android:fromYDelta="0"
    android:toYDelta="0"

    android:duration="500"
    android:startOffset="500"
    android:fillAfter="false"
    android:repeatMode="restart"
    android:repeatCount="1"
    android:interpolator="@android:anim/accelerate_interpolator">
</translate>

6、ScaleAnimation

缩放动画

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="100%p"
    android:toXScale="0.8"
    android:fromYScale="100%p"
    android:toYScale="0.8"
    android:pivotY="0%"
    android:pivotX="0%"

    android:duration="500"
    android:startOffset="500"
    android:fillAfter="false"
    android:repeatMode="restart"
    android:repeatCount="1"
    android:interpolator="@android:anim/accelerate_interpolator">
</scale>

7、AnimationSet

动画集合

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="false"
    android:interpolator="@android:anim/overshoot_interpolator"
    android:repeatMode="reverse"
    android:shareInterpolator="true"
    android:startOffset="500">

    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="1"
        android:toDegrees="360" />

    <scale
        android:fromXScale="50%"
        android:fromYScale="50%"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="1"
        android:toXScale="100%"
        android:toYScale="100%" />

    <translate
        android:fromXDelta="-30%p"
        android:fromYDelta="0"
        android:repeatCount="1"
        android:toXDelta="30%p"
        android:toYDelta="0" />

    <alpha
        android:fromAlpha="1"
        android:repeatCount="1"
        android:toAlpha="0.2" />
</set>

注意:

  1. Set种各个动画创建的顺序,会影响最后的效果。经过反复测试,rotatescale都要在translate之前
  2. repeatCountSet设置不起作用,需要单独各个设置

Java代码创建动画的方式,只示例了AlphaAnimation,其它的都类似,只有AnimationSet特殊一点,如下:

AnimationSet set = new AnimationSet(true);
// 需要将一个个子动画添加进来
set.addAnimation(anim1);
set.addAnimation(anim2);
set.addAnimation(anim3);
// ...... 其他类似

8、监听动画

Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.test);
animation.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        Log.e("补间动画","动画开始了");
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        Log.e("补间动画","动画结束了");
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
        Log.e("补间动画","动画重复播放了");
    }
});
mView.setAnimation(animation);

效果

三、 Property Animatin


本篇暂只介绍属性动画的基本使用,实现补间动画的效果,高级使用方法后续再学习

1、简介

属性动画,3.0之前只有帧动画和补间动画,但是由于这两种动画的动画效果只能作用于View,效果简单并且只改变了View的视觉效果,实际上属性并没有改变,所以在3.0引入了属性动画。

属性动画的工作原理:

在动画持续时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果,可以是任意对象的任意属性

主要类:

  • ViewPropertyAnimator
  • ObjectAnimator
  • ValueAnimator
  • PropertyValuesHolder
  • AnimatorSet

2、特点

  • 可作用于任意Java对象
  • 可定义各种复杂的动画效果
  • 真实改变作用对象的属性

3、ViewPropertyAnimator

该对象的使用是通过Android 3.1系统上新增的一个方法View#animate()方法获取实例。

特点

  • 属性动画简化版,只针对View特定属性,但可以实现补间动画所有效果
  • 简便,链式调用,可同时设置多个动画,自动开始动画
  • 性能更好,多个动画是一次同时变化,只执行一次UI刷新

属性

View的方法 功能 ViewPropertyAnimator的方法
setTranslationX() 设置x轴偏移 translationX() translationXBy()
setTranslationY() 设置y轴偏移 translationY() translationYBy()
setTranslationZ() 设置z轴偏移 translationZ() translationZBy()
setX() 设置x轴绝对位置 x() xBy()
setY() 设置y轴绝对位置 y() yBy()
setZ() 设置z轴绝对位置 z() zBy()
setRotation() 设置平面旋转 rotation() rotationBy()
setRotationX() 设置绕x轴旋转 rotationX() rotationXBy()
setRotationY() 设置绕y轴旋转 rotationY() rotationYBy()
setScaleX() 设置横向缩放 scaleX() scaleXBy()
setScaleY() 设置纵向缩放 scaleY() scaleYBy()
setAlpha() 设置透明度 alpha() alphaBy()

说明:

  • translationX(50) :设置view的translationX属性渐变(动画)为50
  • translationXBy(50) :设置设置view的translationX属性渐变(动画)增加50

使用

/**
 * button点击事件
 */
 public void viewPropertyAnimator(View view) {
 
    // 因为监听事件需要API 21,为了链式调用,直接在这里进行判断了
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    
        iv.animate() // 获取ViewPropertyAnimator
                .translationXBy(50) // 每次点击时x轴递增平移;如果是translationX(50)再次点击不会有效果
                .rotationBy(90) // 平面旋转,同上
                .setDuration(500) // 动画时长
                .setStartDelay(1000) // 开始延迟
                .setInterpolator(new LinearInterpolator()) // 设置插值器,默认AccelerateDecelerateInterpolator
                .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float animatedValue = (float) animation.getAnimatedValue();
                        // 动画更新监听事件,可获取计算出的【完成度】
                        Log.e("完成度",animatedValue+"   translationX:"+(50*animatedValue) + "   rotation:"+(90*animatedValue));

                        // 属性动画,(left,top,right,bottom)是不变的,变化的是(x,y,translationX,translationY) , x = left + translationX
                        Log.d("属性值变化", "getLeft=" + iv.getLeft() + " getX=" + iv.getX() +" getTranslationX=" + iv.getTranslationX());

                    }
                });
    }
}

效果

上面Log中间处省略。ViewPropertyAnimator大概使用如上,其他的动画效果实现也一样,API很简单,练习一下就OK了

4、ObjectAnimator

该对象的特点就完全对应上面第2点所说属性动画的全部特点了,可以作用任意java对象,不过要有相应的setter/getter方法;通过ObjectAnimator.ofxxx()获取ObjectAnimator对象;该对象会根据动画时长自动计算某一时刻的属性值,自动赋值;需要手动调用start()方法播放动画

java实现

public void objectAnimator(View view) {
    // 获取ObjectAnimator
    // 参数1:作用对象
    // 参数2:作用属性,例:setTranslationX -> "translationX" ; setRotationX -> "rotationX",我们的ofFloat也是根据该属性的setter方法参数类型使用的,如果是int,那么我们需要使用ofInt
    // 参数3:可变长参数,-150为开始值 ,0为转接点值 ,150为结束值
    ObjectAnimator animator = ObjectAnimator.ofFloat(iv,"translationX",-150,0,150);
    // 时长
    animator.setDuration(1000);
    // 延迟
    animator.setStartDelay(1000);
    // 重复次数,播放次数 = 重复次数 + 1
    animator.setRepeatCount(0);
    // 重复模式,RESTART:重新开始; REVERSE:反转回来
    animator.setRepeatMode(ValueAnimator.RESTART);
    // 插值器
    animator.setInterpolator(new LinearInterpolator());
    // 动画更新监听
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // 可获取计算出【当前时刻的属性值】
            float animatedValue = (float) animation.getAnimatedValue();
            Log.e("当前属性值",animatedValue+"");

            // 属性动画,(left,top,right,bottom)是不变的,变化的是(x,y,translationX,translationY) , x = left + translationX
            Log.d("属性值变化", "getLeft=" + iv.getLeft() + " getX=" + iv.getX() +" getTranslationX=" + iv.getTranslationX());
        }
    });
    // 开始动画
    animator.start();

}

xml实现

<!-- res/animator目录下创建,各属性含义对比上面 -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="translationX"
        android:valueType="floatType"
        android:valueFrom="-150"
        android:valueTo="150"
        android:duration="1000"
        android:startOffset="1000"
        android:repeatCount="0"
        android:repeatMode="restart"
        android:interpolator="@android:anim/linear_interpolator"/>
</set>
public void objectAnimator(View view) {
    // 加载动画
    Animator animator = AnimatorInflater.loadAnimator(this, R.animator.translation);
    // 作用对象
    animator.setTarget(iv);
    // 开始动画
    animator.start();

}

效果



上图Log,中间有省略

其他动画效果实现方式类似

组合动画: 借助PropertyValuesHolder实现

 public void objectAnimator(View view) {
    // PropertyValuesHolder此类包含有关属性的信息以及该属性在动画期间应采用的值。 
    PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.2f, 1);
    PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.2f, 1);
    PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 0, 360);
    PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0.2f, 1);

    // 获取ObjectAnimator
    ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(iv, scaleX, scaleY, rotation, alpha);
    
    // 开始动画
    animator.setDuration(2000)
            .start();

}

效果

5、ValueAnimator

属性动画中最核心的一个类,此类提供了一个简单的计时引擎,用于运行动画时计算动画值,使用这个类,需要我们手动赋值属性值

xml实现

// res/animator目录下创建
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueType="floatType"
    android:valueFrom="0"
    android:valueTo="360"
    android:duration="2000"
    android:startOffset="1000"
    android:repeatCount="0"
    android:repeatMode="restart"
    android:interpolator="@android:anim/cycle_interpolator"/>
// 加载动画
ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.valueanimator);

java实现

// 获取对象,参数为可变长参数,指定开始值,转接点值,结束值
ValueAnimator animator = ValueAnimator.ofFloat(0, 90, 180, 360);
// 时长
animator.setDuration(2000);
// 延迟
animator.setStartDelay(1000);
// 重复次数
//        animator.setRepeatCount(0);
// 重复模式,RESTART:重新开始; REVERSE:反转回来
//        animator.setRepeatMode(ValueAnimator.RESTART);
// 插值器
animator.setInterpolator(new CycleInterpolator(1f));

设置属性值

// 动画更新监听
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        // 可获取计算出【当前时刻的属性值】
        float animatedValue = (float) animation.getAnimatedValue();
        Log.e("当前属性值", animatedValue + "");

        iv.setRotation(animatedValue);
        iv.setTranslationX(animatedValue);

        // 属性动画,(left,top,right,bottom)是不变的,变化的是(x,y,translationX,translationY) , x = left + translationX
        Log.d("属性值变化", "getLeft=" + iv.getLeft() + " getX=" + iv.getX() + " getTranslationX=" + iv.getTranslationX());

        // 刷新视图
        iv.requestLayout();

    }
});
// 开始动画
animator.start();

效果




上图Log,中间有省略

组合动画一:自己实现
上面的动画组合算是凑巧,下面用另一种方式实现

 public void valueAnimator(View view) {
    // 这里我们设置为 0~1
    ValueAnimator animator = ValueAnimator.ofFloat(0,1);
    // 时长
    animator.setDuration(2000);
    // 延迟
    animator.setStartDelay(1000);
    // 插值器
    animator.setInterpolator(new CycleInterpolator(1f));
    // 动画更新监听
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // 可获取计算出【当前时刻的属性值】,我们当做比例来用
            float animatedValue = (float) animation.getAnimatedValue();
            
            // 2s内,平面旋转0~360 
            iv.setRotation(animatedValue * 360);

            // 2s内,x轴位移,translationX为0~360 
            iv.setTranslationX(animatedValue * 360);

            // 2s内,横向缩放 0.2~1.2
            iv.setScaleX((float) (animatedValue+0.2));

            // 2s内,纵向缩放 0.2~1.2
            iv.setScaleY((float) (animatedValue+0.2));

            // 刷新视图
            iv.requestLayout();

        }
    });
    // 开始动画
    animator.start();

}

组合动画二:借助PropertyValuesHolder实现

public void valueAnimator(View view) {
	// PropertyValuesHolder此类包含有关属性的信息以及该属性在动画期间应采用的值。 
    PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.2f, 1.2f);
    PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.2f, 1.2f);
    PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 0, 360);
    PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("translationX", 0, 360);

    ValueAnimator valueAnimator = ValueAnimator.ofPropertyValuesHolder(scaleX, scaleY, rotation, alpha);
    valueAnimator.setDuration(2000);
    valueAnimator.setInterpolator(new CycleInterpolator(1f));

    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {

            PropertyValuesHolder[] values = animation.getValues();

            for (int i = 0; i < values.length; i++) {
                // 通过PropertyValuesHolder#getPropertyName() 可获得设置的属性
                // 通过ValueAnimator#getAnimatedValue("属性") 可获得计算出的当前时刻属性值
                Log.e("holder", values[i].getPropertyName() + "  " + animation.getAnimatedValue(values[i].getPropertyName()));

                iv.setScaleX((float)animation.getAnimatedValue("scaleX"));
                iv.setScaleY((float)animation.getAnimatedValue("scaleY"));
                iv.setRotation((float)animation.getAnimatedValue("rotation"));
                iv.setTranslationX((float)animation.getAnimatedValue("translationX"));

            }
        }
    });

    valueAnimator.start();

}

效果: (上面两种实现方式的最终效果都是一样的)

6、AnimatorSet

通过上面的学习我们了解到:ObjectAnimator只能改变一个属性,不能直接实现组合动画,需要借助PropertyValuesHolder才行;ValueAnimator也可以直接实现组合动画,也借助PropertyValuesHolder实现;ViewPropertyAnimator可以很方便的实现组合动画;但是它们都有一个缺点:都只能是几种动画效果同时播放;下面我们学习组合动画的正确姿势AnimatorSet

API

AnimatorSet

  • play(Animator anim)
    创建AnimatiorSet.Builder对象

  • playSequentially(Animator… items)
    创建AnimatiorSet.Builder对象,并设置每个动画在上个动画执行完后执行,顺序执行

  • playSequentially(List items)
    同上,只不过是集合形式

  • playTogether(Animator… items)
    创建AnimatiorSet.Builder对象,并设置所有动画同时执行

  • playTogether(Collection items)
    同上,只不过是集合形式

  • setDuration(long duration)
    设置此AnimatorSet的每个子动画的持续时长,优先级高于单独设置

AnimatiorSet.Builder

  • after(Animator anim)
    将现有动画插入到传入的动画之后执行
  • after(long delay)
    将现有动画延迟指定毫秒后执行
  • before(Animator anim)
    将现有动画插入到传入的动画之前执行
  • with(Animator anim)
    将现有动画和传入的动画同时执行

Java实现

public void animatorSet(View view) {
    // 顺序执行 
    AnimatorSet set1 = new AnimatorSet();
    ObjectAnimator translationAnimator1 = ObjectAnimator.ofFloat(iv, "translationX", -300);
    ObjectAnimator translationAnimator2 = ObjectAnimator.ofFloat(iv, "translationY", 600);
    ObjectAnimator translationAnimator3 = ObjectAnimator.ofFloat(iv, "translationX", 300);
    ObjectAnimator translationAnimator4 = ObjectAnimator.ofFloat(iv, "translationY", 0);
    ObjectAnimator translationAnimator5 = ObjectAnimator.ofFloat(iv, "translationX", 0);

    set1.playSequentially(translationAnimator1, translationAnimator2, translationAnimator3, translationAnimator4, translationAnimator5);
    // 设置动画时长,这里的时长是每个子动画的时长
    set1.setDuration(1000);


    // 同时执行
    AnimatorSet set2 = new AnimatorSet();
    ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(iv, "rotationY", 0, 360);
    ObjectAnimator scaleAnimator1 = ObjectAnimator.ofFloat(iv, "scaleX", 0.2f, 1);
    ObjectAnimator scaleAnimator2 = ObjectAnimator.ofFloat(iv, "scaleY", 0.2f, 1);
    ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(iv, "alpha", 0.2f, 1);

    set2.playTogether(rotationAnimator, scaleAnimator1, scaleAnimator2, alphaAnimator);
    // 设置动画时长,这里的时长是每个子动画的时长
    set2.setDuration(5000);

    // 最终组合 , 这里设置时长是每个子动画的时长 , 因为想让set1 和 set2 总时长一样,所以分开设置了
    AnimatorSet set = new AnimatorSet();
    set.playTogether(set1,set2);
    set.start();
}

xml实现

<?xml version="1.0" encoding="utf-8"?>
<!--ordering :together 同时执行 ; sequentially 顺序执行 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
    <!--同时执行 , 给set设置 duration 属性无效 , 所以单独设置-->
    <set android:ordering="together">
        <objectAnimator
            android:propertyName="rotationY"
            android:valueType="floatType"
            android:valueFrom="0"
            android:valueTo="360"
            android:duration="5000"/>
        <objectAnimator
            android:propertyName="scaleX"
            android:valueType="floatType"
            android:valueFrom="0.2"
            android:valueTo="1"
            android:duration="5000"/>
        <objectAnimator
            android:propertyName="scaleY"
            android:valueType="floatType"
            android:valueFrom="0.2"
            android:valueTo="1"
            android:duration="5000"/>
        <objectAnimator
            android:propertyName="alpha"
            android:valueType="floatType"
            android:valueFrom="0.2"
            android:valueTo="1"
            android:duration="5000"/>

    </set>

    <!--顺序执行-->
    <set android:ordering="sequentially">
        <objectAnimator
            android:propertyName="translationX"
            android:valueType="floatType"
            android:valueFrom="0"
            android:valueTo="-300"
            android:duration="1000"/>
        <objectAnimator
            android:propertyName="translationY"
            android:valueType="floatType"
            android:valueFrom="0"
            android:valueTo="600"
            android:duration="1000"/>
        <objectAnimator
            android:propertyName="translationX"
            android:valueType="floatType"
            android:valueFrom="-300"
            android:valueTo="300"
            android:duration="1000"/>
        <objectAnimator
            android:propertyName="translationY"
            android:valueType="floatType"
            android:valueFrom="600"
            android:valueTo="0"
            android:duration="1000"/>
        <objectAnimator
            android:propertyName="translationX"
            android:valueType="floatType"
            android:valueFrom="300"
            android:valueTo="0"
            android:duration="1000"/>
    </set>
</set>
public void animatorSet(View view) {
    // 加载动画 
    Animator animator = AnimatorInflater.loadAnimator(this, R.animator.set);
    // 作用对象
    animator.setTarget(iv);
    // 开始
    animator.start();
}

效果

7、动画监听

  • ViewPropertyAnimator#setUpdateListener() 和 ValueAnimator#addUpdateListener()

    参数都是ValueAnimator.AnimatorUpdateListener,上面也示例过了,只是其中参数都是ValueAnimator#getAnimatedValue()不同:

    ViewPropertyAnimator#setUpdateListener返回的是当前时刻完成度
    ValueAnimator#addUpdateListener返回的是当前时刻的具体属性值

  • ViewPropertyAnimator#setListener() 和 ValueAnimator#addListener()
    参数都是Animator.AnimatorListener,如下:

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

    @Override
    public void onAnimationEnd(Animator animation) {
        // 动画结束、取消时被调用
    }

    @Override
    public void onAnimationCancel(Animator animation) {
        // 动画取消时调用,先调用cancel,再调用end
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
        // 当动画通过 setRepeatMode() / setRepeatCount() 或 repeat() 方法重复执行时,这个方法被调用

        // ViewPropertyAnimator 不支持重复,所以这个方法对 ViewPropertyAnimator 无效
    }
});

四、Interpolator

插值器,就是速度设置器

java xml 效果
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 默认,先加速再减速
AccelerateInterpolator @android:anim/accelerate_interpolator 持续加速
DecelerateInterpolator @android:anim/decelerate_interpolator 持续减速
AnticipateInterpolator @android:anim/anticipate_interpolator 蓄力效果,先回拉再加速动画
OvershootInterpolator @android:anim/overshoot_interpolator 回弹效果,超出终点后再回终点
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 蓄力+回弹
BounceInterpolator @android:anim/bounce_interpolator 结束时有弹跳效果
CycleInterpolator @android:anim/cycle_interpolator 回弹效果,不同于上面的一点回弹,像荡秋千一样,回弹次数由构造中传入值决定
LinearInterpolator @android:anim/linear_interpolator 匀速

个人总结,水平有限,如果有错误,希望大家能给留言指正!如果对您有所帮助,可以帮忙点个赞!如果转载,希望可以标明文章出处!最后,非常感谢您的阅读!

发布了53 篇原创文章 · 获赞 147 · 访问量 10万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览