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 对象功能
alphAlphaAnimation透明度动画
rotateRotateAnimation旋转动画
translateTranslateAnimation位移动画
scaleScaleAnimation缩放动画
setAnimationSet补间动画集合

属性:

xml 属性功能可用于动画
duration动画持续时间ALL
startOffset动画开始延迟时间ALL
fillBefore动画完成后,保持动画前状态,默认trueALL
fillAfter动画完成后,保持动画后状态,默认falseALL
fillEnabled是否使用fillBefore值,对fillAfter值无影响,默认为trueALL
repeatMode重放,restart正序重放,reverse倒序回放,默认restartALL
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

插值器,就是速度设置器

javaxml效果
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匀速

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

  • 10
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值