Android animation basics: attribute animation

Preface

Attribute animation is a newly added feature of API 11. Unlike View animation, it expands the active object. Attribute animation can animate any object, or even no object. Property animation can animate the properties of any object, not just View. The default time interval of the animation is 300ms, and the default frame rate is 10ms/frame. The effect it can achieve is to complete the change of an object from one attribute value to another within a time interval. The open source animation library nineoldandroids is compatible with systems prior to API 11.

Several commonly used animation classes are: ValueAnimator , ObjectAnimator , AnimatorSet , where ObjectAnimator inherits from ValueAnimator, and AnimatorSet is an animation collection that can define a group of animations.

ObjectAnimator

ObjectAnimator is the most important implementation class in the attribute animation framework. To create an ObjectAnimator, you only need to directly return an ObjectAnimator object through its static factory class. The parameters include: an object and the property name of the object, but this property must have get and set functions. The set function is called internally to modify the value of the object property through the Java reflection mechanism. You can also call setInterpolator to set the corresponding interpolator.

  • Panning
val transObj=ObjectAnimator.ofFloat(btn,"translationY",btn.height.toFloat())
transObj.repeatCount=10
transObj.start()

Effect :
Insert picture description here

  • Transparency animation
val colorAnim=ObjectAnimator.ofInt(btn,"backgroundColor",0xFFFF8080.toInt(),0xFF8080FF.toInt())
colorAnim.duration=3000
colorAnim.repeatMode=ValueAnimator.REVERSE
colorAnim.repeatCount=ValueAnimator.INFINITE
colorAnim.setEvaluator(ArgbEvaluator())
colorAnim.start()

effect:
Insert picture description here

AnimatorSet

val set=AnimatorSet()
val colorAnim=ObjectAnimator.ofInt(btn,"backgroundColor",0xFFFF8080.toInt(),0xFF8080FF.toInt(),0xFFFF8080.toInt())

val rotateAnimatorX=ObjectAnimator.ofFloat(btn,"rotationX",0f,360f,0f)
val rotateAnimatorY=ObjectAnimator.ofFloat(btn,"rotationY",0f,180f,0f)

val translationAnimatorX=ObjectAnimator.ofFloat(btn,"translationX",0f,90f,0f)
val translationAnimatorY=ObjectAnimator.ofFloat(btn,"translationY",0f,90f,0f)

val scaleAnimatorX=ObjectAnimator.ofFloat(btn,"scaleX",1f,1.5f,1f)
val scaleAnimatorY=ObjectAnimator.ofFloat(btn,"scaleY",1f,0.5f,1f)

val alpha=ObjectAnimator.ofFloat(btn,"alpha",1f,0.25f,1f)
//使用playTogether
set.playTogether(rotateAnimatorX,rotateAnimatorY,translationAnimatorX,translationAnimatorY,scaleAnimatorX,scaleAnimatorY,alpha,colorAnim)
// 使用 after()、before()、with() 方法
set.play(colorAnim).with(rotateAnimatorY).with(translationAnimatorY).with(alpha).after(scaleAnimatorY)

set.duration=5000 
set.reverse()
set.start()

Effect:
Use playTogether effect
Insert picture description here
Use after(), before(), with() method effects:
Insert picture description here

method

  • Various animation effects in the playTogether(Animator... items) set set are executed simultaneously
  • after (Animator anim)
    insert an existing animation into the incoming animation to execute
  • after(long delay) delay
    the existing animation for specified milliseconds before execution
  • before (Animator anim)
    insert the existing animation into the incoming animation before execution
  • with(Animator anim)
    executes the existing animation and the incoming animation at the same time

PropertyValuesHolder

In property animation, if you want to use multiple animations at the same time for multiple properties of the same object, you can use PropertyValuesHolder to achieve

 val pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f)
 val pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.1f)
 val pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.1f)
 ObjectAnimator.ofPropertyValuesHolder(button, pvh1, pvh2, pvh3).setDuration(1000).start()

Effect :
Insert picture description here

ValueAnimator

ValueAnimator itself does not affect any objects, which means that there is no animation effect when using it directly. It can animate a value, and then can monitor its animation process, and modify the property value of our object during the animation process, which is equivalent to animating our object.

Digital scroll example:

private fun valueAnimEx(btn: Button){
    
    
        val anim=ValueAnimator.ofFloat(0f, 100f)
        anim.addUpdateListener {
    
     animator->
            btn.text="¥${
      
      animator.animatedValue}"
        }
        anim.duration=3000
        anim.interpolator=LinearInterpolator()
        anim.start()
    }

effect:
Insert picture description here

Animate any property

The principle of property animation animation: Property animation requires the object to be animated to provide the get and set methods of the property. The property animation calls the set method multiple times with the effect of the animation according to the initial value and final value of the property passed by the outside world. The values ​​passed to the set method are not the same. To be precise, as time goes by, the passed value gets closer and closer to the final value.

Scenario : Add an animation to the Button to increase the width of the Button to the specified width

Solution

  • Add get and set methods to your object, if you have permission
  • Use a class to wrap the original object and indirectly provide it with set and get methods
  • Use ValueAnimator to monitor the animation process and implement property changes by yourself

The first scheme is not feasible in most cases, unless the premise is permission, this type will not be repeated. The second and third options below

 private fun performAnimate(target: Button,start :Int,end :Int){
    
    
       // 采用ValueAnimator,监听动画过程,自己实现属性的改变
        val valueAnimator=ValueAnimator.ofInt(1,100)
        val mEvaluator=IntEvaluator()

        valueAnimator.addUpdateListener {
    
    animator->
            val fraction=animator.animatedFraction
            target.layoutParams.width=mEvaluator.evaluate(fraction,start,end)
            target.requestLayout()
        }

        valueAnimator.duration=5000
        valueAnimator.start()

        // 用一个类来包装原始对象,间接为其提供set 和get方法
        val viewWrapper=ViewWrapper(target)
        val  objectAnimator=ObjectAnimator.ofInt(viewWrapper,"width",start,end)
        objectAnimator.duration=5000
        objectAnimator.start()
    }
   inner class ViewWrapper{
    
    
        private var viewTarget: View?=null

        constructor(viewTarget: View?) {
    
    
           this.viewTarget = viewTarget
        }

        fun setWidth(width :Int){
    
    
            viewTarget?.layoutParams?.width=width
            viewTarget?.requestLayout()
        }

        fun getWidth():Int?{
    
    
            return viewTarget?.layoutParams?.width
        }
    }

effect:
Insert picture description here

Related API

  • Property animation listener
public static interface AnimatorListener {
    
    
 
     void onAnimationStart(Animator animation);
     
     void onAnimationEnd(Animator animation);
     
     void onAnimationCancel(Animator animation);
     
     void onAnimationRepeat(Animator animation);
 }
 
 public static interface AnimatorUpdateListener {
    
    
 
     void onAnimationUpdate(ValueAnimator animation);
 }
  • Xml layout attributes
 // set标签 对应 AnimatorSet
<set xmlns:android="http://schemas.android.com/apk/res/android"
    //together 表示动画集合中子动画同时播放
    //sequentially 表示动画集合中子动画 按照前后顺序依次播放
    android:ordering=["together"|"sequentially"]>

   // animator标签 对应 ValueAnimator
    <animator
        // 表示动画时长
        android:duration="int"
        //表示属性动画作用对象的属性的名称
        android:propertyName="string" 
        // 表示动画的重复 0默认值,-1逆向重复
        android:repeatCount="int"
         // 表示动画的重复模式 reverse逆向重复,restart连续重复
        android:repeatMode=["reverse"|"restart"]
        // 动画延时的时间
        android:startOffset="int"
        // 属性的起始值
        android:valueFrom="float|color|int"
        // 属性的结束值
        android:valueTo="float|color|int"
        // 表示android:propertyName所指定的属性的类型,如果所指定的属性值是颜色
        // 那么不需要指android:valueType,系统会自动对颜色类型的属性做处理
        android:valueType=["intType"|"floatType"]/>

   // objectAnimator标签 对应 ObjectAnimator
    <objectAnimator
        android:duration="int"
        android:propertyName="string"
        android:repeatCount="int"
        android:repeatMode=
        android:startOffset="int"["reverse"|"restart"]
        android:valueFrom="float|color|int"
        android:valueTo="float|color|int"
        android:valueType=["intType"|"floatType"] />
</set>

Guess you like

Origin blog.csdn.net/xufei5789651/article/details/113316163