Android 补间动画及组合AnimationSet常用方法详解

手机APP/开发
348
0
0
2023-06-09
标签   Android
目录
  • 补间动画
  • RotateAnimation
  • 动画示例
  • ScaleAnimation
  • 动画示例
  • TranslateAnimation
  • 动画示例
  • AlphaAnimation
  • 动画示例
  • AnimationSet 动画组合
  • 动画示例

补间动画

Android常用的四种补间动画分别为RotateAnimation、ScaleAnimation、TranslateAnimation、AlphaAnimation,他们的父类为Animation,UML类图如下:

父类通用方法有:

  • public void setFillBefore(boolean fillBefore): 动画完成后,View是否会停留在动画开始的状态,默认为true
  • public void setFillAfter(boolean fillAfter) :动画完成后,View是否会停留在动画结束的状态,优先级大于fillBefore,默认为false
  • public void setFillEnabled(boolean fillEnabled) :控制setFillBefore的值是否生效,如果fillEnabled为false,则setFillBefore无论为何值都不会再生效。
  • public boolean isFillEnabled():返回setFillEnabled设置的值。
  • public void setStartOffset(long startOffset):设置动画延迟启动时间,单位是ms
  • public void setDuration(long durationMillis):设置动画持续时间,如果设置durationMillis < 0会抛异常。
  • public void setRepeatMode(int repeatMode):RESTART:正序重新开始、REVERSE:倒序重新开始,默认是RESTART。注意:repeatCount(count)设置的count值必须>0或者是INFINITE才会生效
  • public void setRepeatCount(int repeatCount):设置动画应该重复的次数。如果为0,则动画只播放一次;如果设置为N(N>0),则将继续播放N次;如果设置为INFINITE,则将无限轮播。默认为0。
  • public void setInterpolator(Interpolator i):设置差值器,影响动画的加速曲线。默认为AccelerateDecelerateInterpolator。
  • public void setAnimationListener(AnimationListener listener) : 设置动画监听,AnimationListener中的几个方法如下:
animation.setAnimationListener(object : Animation.AnimationListener {
                override fun onAnimationEnd(animation: Animation?) {
                    //动画结束时回调,注意:当repeatCount设置为Animation.INFINITE不再收到该回调
                    log("onAnimationEnd")
                }
                override fun onAnimationStart(animation: Animation?) {
                    //动画开始时回调
                    log("onAnimationStart")
                }
                override fun onAnimationRepeat(animation: Animation?) {
                    //repeatCount设置为Animation.INFINITE时动画每执行一次该方法回调就会执行一次
                    log("onAnimationRepeat")
                }
            })

RotateAnimation

旋转动画,通过设置目标View的旋转中心、旋转角度来达到旋转目的。RotateAnimation中需要特殊设置的几个参数如下:

// RotateAnimation.java
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
            int pivotYType, float pivotYValue) {
    mFromDegrees = fromDegrees;
    mToDegrees = toDegrees;
    mPivotXValue = pivotXValue;
    mPivotXType = pivotXType;
    mPivotYValue = pivotYValue;
    mPivotYType = pivotYType;
    initializePivotPoint();
 }
  • fromDegrees:动画开始之前的旋转偏移量
  • toDegrees:动画结束时的旋转偏移量
  • pivotXType:用于设置旋转中心X轴计量类型,可以设置成Animation.ABSOLUTE、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT之一,pivotXType与pivotXValue组合之后可以表示不同的X轴坐标点。
Animation.ABSOLUTE:目标View的X轴坐标 = View左上角的原点 + pivotXValue数值的点(y方向同理)
Animation.RELATIVE_TO_SELF:目标View的X轴坐标 = View左上角的原点 + View自身宽度 * pivotXValue数值
Animation.RELATIVE_TO_PARENT:目标View的X轴坐标 = View左上角的原点 + View父控件宽度 * pivotXValue
  • pivotXValue:旋转View所围绕的点的X坐标。如果pivotXType为absolute,此值可以是一个绝对数字,否则可以是一个0.1f~1.0f 的值。
  • pivotYType:同pivotXType,表示的的是y轴
  • pivotYValue:同pivotXValue,表示的的是y轴

动画示例

方式一:代码动态创建

val rotateAnim: Animation = RotateAnimation(f,
f,
            Animation.RELATIVE_TO_SELF,.5f,
            Animation.RELATIVE_TO_SELF,.5f
        )
rotateAnim.duration =
rotateAnim.repeatCount = Animation.INFINITE
rotateAnim.interpolator = LinearInterpolator()
rotateAnim.fillAfter = true
mTvTarget.animation = rotateAnim

方式二:XML中设置

//view_rotate.xml中:
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration=""
    android:fillAfter="true"
    android:fromDegrees=""
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="%"
    android:pivotY="%"
    android:repeatCount="infinite"
    android:repeatMode="restart"
    android:toDegrees="" />

代码中引用:

mTvTarget.startAnimation(AnimationUtils.loadAnimation(this, R.anim.view_rotate))

执行效果:

在XML中设置pivotX、pivotY时注意:pivotX pivotY,可取值为数字,百分比,或者百分比p

  • 设置为数字时,表示px像素值。如设置为10,那么中心坐标为View的左上角的原点在x方向和y方向加上10px的点。对应代码中的Animation.ABSOLUTE单位。
  • 设置为百分比时(如50%),中心坐标为View的左上角的原点在x方向加上自身宽度50%和y方向自身高度50%的点(即自身中间的位置)。对应代码中的Animation.RELATIVE_TO_SELF。
  • 设置为百分比p时(如50%p),中心坐标为View的左上角的原点在x方向加上父控件宽度50%和y方向父控件高度50%的点。对应代码中的Animation.RELATIVE_TO_PARENT

ScaleAnimation

缩放动画,设置的参数如下:

public ScaleAnimation(float fromX, float toX, float fromY, float toY,
        int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
    mResources = null;
    mFromX = fromX;
    mToX = toX;
    mFromY = fromY;
    mToY = toY;
    mPivotXValue = pivotXValue;
    mPivotXType = pivotXType;
    mPivotYValue = pivotYValue;
    mPivotYType = pivotYType;
    initializePivotPoint();
}
  • fromX / toX:分别表示X轴方向在动画开始时、结束时对应的缩放因子
  • fromY / toY:分别表示Y轴方向在动画开始时、结束时对应的缩放因子
  • pivotXType、pivotXValue、pivotYType、pivotYValue具体含义在上面的RotateAnimation已经讲到,这四个值在ScaleAnimation主要是用来确定缩放中心的。

动画示例

方式一:代码动态创建

val scaleAnim = ScaleAnimation(.0f, 0.5f, 1.0f, 0.5f,              Animation.RELATIVE_TO_SELF,.5f,
            Animation.RELATIVE_TO_SELF,.5f).apply {
        duration =
        repeatCount = Animation.INFINITE
        repeatMode = Animation.REVERSE
        fillAfter = true
    }
mTvTarget.animation = scaleAnim

方式二:XML中创建

// view_scale.xml
<scale xmlns:android="http://schemas.android.com/apk/res/android"  android:duration=""
android:fillAfter="true"
android:fromXScale=".0"
android:fromYScale=".0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="%"
android:pivotY="%"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXScale=".5"
android:toYScale=".5" />

代码中引入:

mTvTarget.startAnimation(AnimationUtils.loadAnimation(this, R.anim.view_scale))

执行结果:

TranslateAnimation

平移动画,是指对目标View进行平移操作。

public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
    mFromXValue = fromXDelta;
    mToXValue = toXDelta;
    mFromYValue = fromYDelta;
    mToYValue = toYDelta;
    mFromXType = ABSOLUTE;
    mToXType = ABSOLUTE;
    mFromYType = ABSOLUTE;
    mToYType = ABSOLUTE;
}
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
        int fromYType, float fromYValue, int toYType, float toYValue) {
    mFromXValue = fromXValue;
    mToXValue = toXValue;
    mFromYValue = fromYValue;
    mToYValue = toYValue;
    mFromXType = fromXType;
    mToXType = toXType;
    mFromYType = fromYType;
    mToYType = toYType;
}

可以看到有两个不同的构造方法:

  • 第一种把类型固定为ABSOLUTE,那么传入的float fromXDelta, float toXDelta, float fromYDelta, float toYDelta都为固定数值,即(fromXDelta, fromYDelta)、(toXDelta、toYDelta)分别代表起始坐标与结束坐标。
  • 第二种传入的类型可以为 Animation.ABSOLUTE、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT 的一种,那么对应的fromXValue、toXValue、fromYValue、toYValue 可以是具体数值或或者0.0~1.0(表示目标View本身或着父View的百分比)。

动画示例

方式一:代码动态创建

val translateAnim = TranslateAnimation(          Animation.ABSOLUTE,f, Animation.RELATIVE_TO_SELF, 0.5f,
        Animation.ABSOLUTE,f, Animation.RELATIVE_TO_SELF, 0.5f)
 .apply {          duration =
        fillAfter = false
        interpolator = LinearInterpolator()
        repeatMode = Animation.REVERSE
        repeatCount = Animation.INFINITE
    }
mTvTarget.animation = translateAnim

方式二:XML中创建

// view_translate.xml
<?xml version=".0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"  android:duration=""
android:fillAfter="true"
android:fromXDelta=""
android:fromYDelta=""
android:interpolator="@android:anim/linear_interpolator"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXDelta="%"
android:toYDelta="%" />

代码中引入:

mTvTarget.startAnimation(AnimationUtils.loadAnimation(this, R.anim.view_translate))

执行效果:

AlphaAnimation

透明度动画

public AlphaAnimation(float fromAlpha, float toAlpha) {
    mFromAlpha = fromAlpha;
    mToAlpha = toAlpha;
}
  • fromAlpha: 动画开始时的透明度: 1.0表示完全不透明,0.0表示完全透明
  • toAlpha: 动画结束时透明度: 1.0表示完全不透明,0.0表示完全透明

动画示例

方式一:代码动态创建

val alphaAnim = AlphaAnimation(.0f, 0.2f).apply {          duration =
        fillAfter = true
        interpolator = LinearInterpolator()
        repeatMode = Animation.REVERSE
        repeatCount = Animation.INFINITE
    }
mTvTarget.animation = alphaAnim

方式二:XML中创建

//view_alpha.xml
<alpha xmlns:android="http://schemas.android.com/apk/res/android"  android:duration=""
android:fillAfter="true"
android:fromAlpha=".0"
android:interpolator="@android:anim/linear_interpolator"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toAlpha=".0" />

代码中引入:

mTvTarget.startAnimation(AnimationUtils.loadAnimation(this, R.anim.view_alpha))

执行效果:

AnimationSet 动画组合

动画组合AnimationSet,本身也继承自Animation,可以将多个动画组合起来使用。如下属性在AnimationSet中设置时的注意事项:

  • duration, repeatMode, fillBefore, fillAfter: 当在AnimationSet对象上设置这些属性时,将被下推到所有子动画。
  • repeatCount, fillEnabled: 这些属性在AnimationSet中被忽略。
  • startOffset, shareInterpolator: 这些属性应用于AnimationSet本身。

动画示例

方式1:代码动态生成

/**
 * 动画组合AnimationSet
 * - duration, repeatMode, fillBefore, fillAfter:当在AnimationSet对象上设置这些属性时,将被下推到所有子动画。
 * - repeatCount, fillEnabled:这些属性在AnimationSet中被忽略。
 * - startOffset, shareInterpolator: 这些属性应用于AnimationSet本身
 */
private fun loadAnimSet(): Animation {
    //方式:代码动态生成
    val rotateAnim = loadRotationAnim()
    val alphaAnim = loadAlphaAnimation()
    val translateAnim = loadTranslateAnimation()
    val scaleAnim = loadScaleAnimation()
    /**
     * shareInterpolator: 如果想让集合中的所有动画都使用与AnimationSet中
     * 设置的一样的插值器,则传true;反之,如果集合中每个动画都使用自己的插值器,则传false.
     */
    val animSet = AnimationSet(true).apply {
        duration =
        interpolator = LinearInterpolator()
        fillAfter = true
        repeatMode = Animation.REVERSE
        startOffset = //延迟执行动画,应用于AnimationSet本身
    }
    //animSet.cancel() //取消动画
    //animSet.reset() //重置动画
    animSet.addAnimation(rotateAnim)
    animSet.addAnimation(alphaAnim)
    animSet.addAnimation(translateAnim)
    animSet.addAnimation(scaleAnim)
    return animSet
}
mTvTarget.startAnimation(loadAnimSet())

方式2:通过XML创建:

//view_animation_set.xml
<?xml version=".0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"  android:duration=""
android:fillAfter="true"
android:fillBefore="false"
android:interpolator="@android:anim/linear_interpolator"
android:repeatMode="reverse"
android:shareInterpolator="true">
<rotate
    android:fromDegrees=""
    android:pivotX="%"
    android:pivotY="%"
    android:repeatCount="infinite"
    android:toDegrees="" />
<scale
    android:fromXScale=".0"
    android:fromYScale=".0"
    android:pivotX="%"
    android:pivotY="%"
    android:repeatCount="infinite"
    android:toXScale=".5"
    android:toYScale=".5" />
<!-- startOffset:延迟执行动画-->
<set
    android:fillAfter="true"
    android:interpolator="@android:anim/linear_interpolator"
    android:repeatMode="reverse"
    android:shareInterpolator="true"
    android:startOffset="">
    <alpha
        android:fromAlpha=".0"
        android:repeatCount="infinite"
        android:toAlpha=".0" />
    <translate
        android:fromXDelta=""
        android:fromYDelta=""
        android:repeatCount="infinite"
        android:toXDelta="%"
        android:toYDelta="%" />
</set>
</set>

代码中引入:

mTvTarget.startAnimation(AnimationUtils.loadAnimation(this, R.anim.view_animation_set))

执行结果: