Android - 动画

一、概念

属性动画PeopertyAnimation:view的属性根据执行的动画发生真实的改变。通过不断设置 View 的属性实现。
补间动画 ViewAnimation(Tween):不改变view的位置和属性。基于 Framework的绘制转变。
帧动画 DrawableAnimation(Frame):依次播放动画过程中每帧对应的静态图片。

二、插值器 Interpolator

即数度模型,算法对应不同时间点动画完成度的百分比。

LinearInterpolator 匀速。
AccelerateInterpolator 持续加速(构造中可调节变速系数)。主要用在出场效果中。
AccelerateDecelerateInterpolator 先加速再减速。默认效果,最符合现实物理模型。
DecelerateInterpolator 持续减速到0。主要用于入场效果。
AnticipateInterpolator 先反效果一点点(平移就是先回拉,放大就是先缩小),再进行正常动画轨迹。
OvershottInterpolator 超过目标值一些再弹回来。
AnticipateOvershootInterpolator 两种效果的结合体,先反效果一点点,最后超过目标值一些再回弹。
BounceInterpolator 在目标值处弹跳几下。
CycleInterpolator 自定义动画循环播放特定次数。
PathInterpolator 自定义任何想要的速度模型(动画完成度 ÷ 时间完成度)。使用一个 Path 对象来绘制出想要的曲线(y 为动画完成度,x 为时间完成度)。

FastOutLinearInInterpolator

持续加速(贝塞尔曲线,初始加速更快,肉眼并不明显)。
FastOutSlowInInterpolator 先加速再减速(贝塞尔曲线,加速减速更快)。
LinearOutSlowInInterpolator 持续减速(初始速度更快)。

三、属性动画PeopertyAnimation

3.1 ViewPropertyAnimator

通过 view.animate() 返回一个 ViewPropertyAnimator 对象并自动执行,局限性在于只能调用以下方法设置属性动画。

public ViewPropertyAnimator animate()

3.1.1 动画模式 

  • 这些方法调用就会执行动画,在播放中途再次调用会先停留在原处,等进度赶上了再继续播放。当动画播放完毕后,不带by的方法再次调用不会执行,任何时候调用 start( ) 都无效果,调用 cancel() 会打断动画并会停留在原处,再次这些方法等进度赶上了再继续播放。
  • 默认动画时长0.3s,通过 setDuration() 自定义。
  • 默认速度模型开始加速结束减速(AccelerateDecelerateInterpolator),通过 setInterpolator() 自定义。

3.1.2 动画监听

设置监听

public @NonNull ViewPropertyAnimator setListener(@Nullable Animator.AnimatorListener listener)

重写onAnimationStart动画开始、onAnimationEnd动画结束、onAnimationCancel动画取消(对应调用了cancel时)、onAnimationRepeat动画重复(对应通过repeat播放时)。

更新监听

public @NonNull ViewPropertyAnimator setUpdateListener(@Nullable ValueAnimator.AnimatorUpdateListener listener)

重写onAnimationUpdate每当属性值更新时,参数ValueAnimator可以获取当前动画完成度、属性值等。

一次性监听

public @NonNull ViewPropertyAnimator withStartAction(Runnable runnable) 

public @NonNull ViewPropertyAnimator withEndAction(Runnable runnable) 

重用ViewPropertyAnimator 执行别的动画也不会再执行,动画被调用cancel取消时不会再执行。

3.2 ObjectAnimator

ofFloat(Object target, String propertyName, float... values)
ofInt(Object target, String propertyName, int... values)
ofArgb(Object target, String propertyName, int... values)
ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)
ofMultiFloat(Object target, String propertyName, TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values)
ofMultiInt(Object target, String propertyName, TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values)

通过 ObjectAnimator.ofXXX() 创建对象,XXX具体选什么类型根据该属性设置方法的参数类型决定。target是目标View,propertyName是View的哪个属性(不是找同名变量修改值,是拼接出setter方法并调用,找不到IDE会提示。若是自定义View该属性需要提供setter方法,并在最后一行调用 invalidate() 触发重绘),values是目标值(填一个就是目标值,填两个就是起始值和目标值,填多个就是增加中间转接点值。若是自定义View,只填一个值的情况就需要该属性提供getter方法,会获取当前值当作起始值)。调用 start() 才会执行动画。

class MyView2 : View {
    var progress = 0F
    set(value) {
        field = value
        invalidate()    //重写getter触发重绘即调用onDraw()
    }
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.drawArc(...)
    }
}

UI {
    val animator = ObjectAnimator.ofFloat(myView, "progress", 0, 65)
    animator.start()
}

3.2.1 动画监听

设置监听

public void addListener(AnimatorListener listener)

重写onAnimationStart动画开始、onAnimationEnd动画结束、onAnimationCancel动画取消(对应调用了cancel时)、onAnimationRepeat动画重复(对应通过repeat播放时)。

更新监听

public void addUpdateListener(AnimatorUpdateListener listener) 

重写onAnimationUpdate每当属性值更新时,参数ValueAnimator可以获取当前动画完成度、属性值等。

暂停监听 public void addPauseListener(AnimatorPauseListener listener)
var boolean = false
onCreate {
    //对View启用动画
    val animate = imagineView.animate().apply {
        //动画类型不能写在里面因为调用就会执行
        duration = 2000 //设置动画时长
        interpolator = AccelerateDecelerateInterpolator()   //设置速度模型
        startDelay = 2000   //延迟播放
        setListener(object : Animator.AnimatorListener{
            override fun onAnimationStart(animation: Animator) { }  //动画开始
            override fun onAnimationEnd(animation: Animator) { }    //动画结束
            override fun onAnimationCancel(animation: Animator) { } //动画取消
            override fun onAnimationRepeat(animation: Animator) { } //动画重复
        })
        setUpdateListener { valueAnimator -> } //动画更新
        withStartAction { Runnable {  } }  //动画开始
        withEndAction { Runnable {  } }    //动画结束
    }
    button1.setOnClickListener {
        //中途再次点击会停留在原地等进度赶上了继续播放
        animate.translationXBy(200F)    //每次点击都有位移效果
        animate.rotation(180F)  //只执行一次,播放完后再次点击无旋转效果

    }
    button2.setOnClickListener {
        //每次点击在strat和cancel切换,测试结果:start()任何时候都无效,cancel()打断动画停在原地
        if (boolean) animate.start() else animate.cancel()
        boolean = !boolean  
    }
}

四、切换界面动画 Transition

五、补间动画 ViewAnimation(Tween)

5.1 动画模式

透明度

AlphaAnimation(float fromAlpha, float toAlpha)

fromAlpha:起始透明度。

toAlpha:结束透明度,透明度的范围为0-1。

缩放

ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

fromXScale/fromYScale:沿着X轴/Y轴缩放的起始比例。

toXScale/toYScale:沿着X轴/Y轴缩放的结束比例。

pivotX/pivotY:缩放的中轴点X/Y坐标,即距离自身左边缘的位置,比如50%就是以图像的中心为中轴点。

移动

TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)

fromXDelta/fromYDelta:动画起始位置的X/Y坐标。

toXDelta/toYDelta:动画结束位置的X/Y坐标。

旋转

RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

fromDegrees/toDegrees:旋转的起始/结束角度。

动画集合

AnimationSet(boolean shareInterpolator)

可同时播放以上动画。shareInterpolator:true都用一样的插值器,false用各自的插值器。通过调用addAnimation(Animation a) 将动画添加进集合。

5.2 动画配置

持续时间 public void setDuration(long durationMillis)
重复次数

public void setRepeatCount(int repeatCount) 

值为-1或者infinite时,表示动画永不停止。

重复模式

public void setRepeatMode(int repeatMode)

默认restart,但只有当repeatCount大于0或者infinite或-1时 才有效。还可以设置成reverse,表示偶数次显示动画时会做方向相反的运动。

设置速度模型

public void setInterpolator(Interpolator i)

停留结果

public void setFillAfter(boolean fillAfter)

设为 true 则动画结束后 view 会停留在当前效果。

开始动画

public void startAnimation(Animation animation)

传入要播放的动画。

5.3 动画监听

public void setAnimationListener(AnimationListener listener)

用动画对象调用,重写三个方法:onAnimationStart动画开始时、onAnimationEnd动画结束时、onAnimationRepeat动画重复时。

5.4 使用方式

5.4.1 xml配置动画

res目录下新建anim文件夹,创建xml文件,可选节点有alpha、rotate、scale、translate、set。

<translate xmlns:android="http://schemas.android.com/apk/res/android"  
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"  
    android:fromXDelta="0"  
    android:toXDelta="320"  
    android:fromYDelta="0"  
    android:toYDelta="0"  
    android:duration="2000"/>
AnimationUtils.loadAnimation(this, R.anim.translate)    //加载Xml文件中的动画
imagineView.startAnimation(translate)    //将动画设置到指定的View上

5.4.2 代码配置动画

val imagineView = binding.imagineView
val button = binding.button
//透明
val alphaAnimation = AlphaAnimation(1.0F, 0.2F)
//旋转
val rotateAnimation = RotateAnimation(0F, 360F, Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F)
//缩放
val scaleAnimation = ScaleAnimation(1.0F, 5.0F, 1.0F, 5.0F, Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F)
//平移
val translateAnimation = TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0F, Animation.RELATIVE_TO_PARENT, 0F,Animation.RELATIVE_TO_PARENT, 0F, Animation.RELATIVE_TO_PARENT, 0.4F)
//动画集合
val set = AnimationSet(true).apply {
    addAnimation(alphaAnimation)
    addAnimation(rotateAnimation)
    addAnimation(scaleAnimation)
    addAnimation(translateAnimation)
    duration = 1     //持续时间
    repeatCount = 10    //重复次数
    repeatMode = Animation.RESTART  //重复方式
    interpolator = AccelerateDecelerateInterpolator() //速度模型
    fillAfter = true //播放完毕后停留在原地
}
//动画监听
set.setAnimationListener(object : AnimationListener {
    override fun onAnimationStart(animation: Animation?) { }    //动画开始
    override fun onAnimationEnd(animation: Animation?) { }    //动画结束
    override fun onAnimationRepeat(animation: Animation?) { }    //动画重复
})
button.setOnClickListener {
    imagineView.startAnimation(set) //开始动画
}

六、帧动画 DrawableAnimation(Frame)

6.1 xml配置

res/drawable目录下创建animation-list文件

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">	//true表示只播放一边,默认就是false可不写
    <item android:drawable="@drawable/girl_1" android:duration="100" />
    <item android:drawable="@drawable/girl_2" android:duration="100" />
    <item android:drawable="@drawable/girl_3" android:duration="100" />
</animation-list>

 6.2 代码调用

imagineView.setBackgroundResource(R.drawable.anim_frame)
val animationDrawable = imagineView.background as AnimationDrawable
animationDrawable.start()

猜你喜欢

转载自blog.csdn.net/HugMua/article/details/130498433