La explicación de animación más completa para android.

Las animaciones de Android se dividen en tres tipos: animación de vista, animación de fotogramas y animación de atributos.

Ver animación

¿Qué es ver animación? El objeto de la animación solo puede ser ver animación, que se llama ver animación. Hay cuatro tipos de animación de vista: TranslateAnimation (traducción), ScaleAnimation (zoom), RotateAnimation (rotación) y AlphaAnimation (transparencia). También hay un AnimationSet (animación combinada) y todos heredan la clase Animation . Recuerde que la animación de la vista se logra mediante configuraciones relacionadas con Convas, en lugar de cambiar las propiedades de la vista, por lo que surgirá un problema: la vista se traduce, pero el evento de clic no cambia.

Recuerde que las coordenadas de origen de todas las animaciones son relativas al vértice superior izquierdo de la Vista.

Hay dos formas de implementar la animación de vista: implementación de código dinámico e implementación de archivos xml. Se recomienda utilizar xml, que tiene una gran reutilización.

 Cuando se usa en xml, se debe crear un archivo xml. La ruta del archivo es: res/anim/filename.xml

TraducirAnimaciónAnimación

Código:

Si no se especifica fromXType, el valor predeterminado es ABSOLUTO.

 Hay tres métodos de construcción como se indicó anteriormente.

formXType : especifica cómo se debe interpretar fromXValue. Hay tres modos:

ABSOLUTO //Valor absoluto, la unidad es px
RELATIVE_TO_SELF //Relativo a sí mismo, es decir, el ancho del propio fromXValue*
RELATIVE_TO_PARENT //Relativo a la clase principal, es decir, desdeXvalue*ancho de la clase principal

Propiedades de uso común:

duración: duración de la animación, el valor predeterminado es 0, lo que significa inmediatamente
fillAfter: después de ejecutar la animación, si se debe mantener la posición final
fillBefore: una vez finalizada la animación, si se debe mantener la posición inicial
repetirCount: la animación se repite, el valor predeterminado es 1 vez, -1 representa un bucle no válido
repetirModo: modo de repetición de animación Animation.REVERSE (repetir en dirección inversa después de que finaliza la animación) Animation.RESTART (comenzar de nuevo cada vez)
interpolador: interpolador de animación, cambios a lo largo del tiempo, cambio porcentual de las propiedades de la animación
restablecer: restablecer la animación
setStartOffset: cuánto tiempo se retrasa la animación en relación con la hora de inicio, compensación-compensación
setStartTime: establece el tiempo específico para la ejecución de la animación, la unidad es el tiempo de inicio en milisegundos.
cancelar(): Detiene la animación y detiene la animación de la vista al mismo tiempo. También puedes usar it.clearAnimation(). La diferencia es que cancelar detiene la animación especificada y clearAnimation() detiene la animación que afecta la vista actual. devolverá la llamada al método onAnimationEnd.
implementación xml:

Primero crea la carpeta anim en res, 

Seleccione la opción de animación hacia arriba, el nombre solo puede ser una animación fija. 

Después de la creación, haga clic derecho y cree una animación xml.

Crear slide_1.xml  

第一种写法:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    >
<translate
    android:duration="500"
    android:fillAfter="true"
    android:fromXDelta="0"
    android:toXDelta="200"
    ></translate>
</set>

<set>是animationSet的xml写法,如果这样写的话,会发现一个问题,就是在<tramslate  标签里面,基本不会提示duration等,这个时候把xmlns:android="http://schemas.android.com/apk/res/android"引用写到<translate>标签中就可以了。

第二种写法:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fillAfter="true"
    android:fromXDelta="0"
    android:toXDelta="200"
    >
</translate>

No hay atributos formXType o formYType en xml , entonces, ¿cómo expresarlos?

android:toYDelta="50" sin modificador, representa ABSOLUTO, la unidad es px

android:toYDelta="50%" // %代表RELATIVE_TO_SELF

android:toYDelta="50%p" // %p代表 RELATIVE_TO_PARENT

usar:

      val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_1)
                it.startAnimation(loadAnimation)

Configurar el monitoreo:

     loadAnimation.setAnimationListener(object :AnimationListener{
                override fun onAnimationStart(animation: Animation?) {
                }

                override fun onAnimationEnd(animation: Animation?) {
                }

                override fun onAnimationRepeat(animation: Animation?) {
                }

            })

EscalaAnimaciónAnimación

  Código:

 Explicación de parámetros:

fromX: comienza a escalar desde 0,5 veces la longitud de su propio eje X. (La atención especial no se refiere al valor de escala en px.) Por ejemplo: fromX= 0,5 significa comenzar desde 0,5 veces la longitud de su propio eje X.

tox: La escala termina en cuántas veces la longitud de su propio eje X. Por ejemplo: toX = 2.0 significa que la escala del eje x termina en 2 veces la longitud de su propio eje x.

formY: comience a escalar desde 0,5 veces la longitud de su propio eje Y. Por ejemplo: fromY=0,5 significa comenzar desde 0,5 veces la longitud de su propio eje Y.

toY: cuántas veces se ampliará la longitud del eje Y, por ejemplo: toY = 2,0, lo que significa que el eje Y se ampliará al doble de la longitud del eje Y.

pivote (punto central)

pivotX: Iniciar escalado relativo a la posición del eje de control X

pivotY: comienza a escalar en relación con la posición del eje de control y

pivotXType: explica el significado del valor pivotx, el valor predeterminado es ABSOLUTO

pivotYType: explica el significado del valor de pivote, el valor predeterminado es ABSOLUTO

Cabe señalar que al hacer zoom, pivotx y pivoty se utilizan como puntos centrales para hacer zoom en ambos lados al mismo tiempo.

implementación xml:
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<scale
    android:duration="500"
    android:fillAfter="true"
    android:fromXScale="1"
    android:toXScale="0.5"
    android:fromYScale="1"
    android:toYScale="0.5"
    android:pivotY="50%"
    android:pivotX="50%"
    ></scale>
</set>
切记,不要在xml中添加float的修饰符 f,不然编译不过
如:
<scale
    android:duration="500"
    android:fillAfter="true"
    android:fromXScale="1"
    android:toXScale="0.5f"   //这样编译不过
    android:fromYScale="1"
    android:toYScale="0.5"
    android:pivotY="50%"
    android:pivotX="50%"
    ></scale>

RotateAnimationanimación de rotación

Código:

 formDegrees: Desde qué ángulo comenzar la rotación

toDegrees: ¿A cuántos grados terminará la rotación?

pivotX: en la posición central de rotación del eje X

pivoty: posición del centro de rotación en el eje y

pivotXtype: explica el significado de pivotx, el valor predeterminado es ABSOLUTO

Animación de transparencia AlphaAnimation

    /**
     * Constructor to use when building an AlphaAnimation from code
     * 
     * @param fromAlpha Starting alpha value for the animation, where 1.0 means
     *        fully opaque and 0.0 means fully transparent.
     * @param toAlpha Ending alpha value for the animation.
     */
    源码的注解已经说明,透明度的值是0.0-1.0
    public AlphaAnimation(float fromAlpha, float toAlpha) {
        mFromAlpha = fromAlpha;
        mToAlpha = toAlpha;
    }
Código:
     val alphaAnimation = AlphaAnimation(1f, 0f).
               apply {
                   duration =500
               }
              it.startAnimation(alphaAnimation)
implementación xml

anim->nuevo->archivo de recursos de animaltion ->

 En este momento, descubrí que no se puede escribir mucho código, como la duración. En este momento, puede envolver una etiqueta establecida en la capa exterior, copiar el valor y luego eliminar la etiqueta <set>.

<?xml versión="1.0" codificación="utf-8"?> 
<alpha xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromAlpha="1" 
   android:duración ="500" 
    android:toAlpha="0.5" 
    />

AnimationSet animación combinada

Combina múltiples animaciones

Código

Ejecutado a través del método addAnimation de AnimationSet.

val apply = AnimationSet(true).apply {
    addAnimation(RotateAnimation(
        0f, -90f, Animation.RELATIVE_TO_SELF, 0.5f,
        Animation.RELATIVE_TO_SELF, 0.5f
    ).apply {
        duration = 300
    })
    addAnimation(AlphaAnimation(1.0f, 0.3f).apply {
        duration = 300
        startOffset = 300
    })
}
it.startAnimation(apply)
Ejecutar en xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:interpolator="@android:anim/linear_interpolator" //动画集合的插值器
    android:shareInterpolator="true"  
   //表示动画集合是否共享一个插值器,如果不指定插值器,那么子动画就需要自己指定插值器,或者使用默认的
    android:fillAfter="true"
    >
<rotate
    android:fromDegrees="0"
    android:toDegrees="90"
    ></rotate>

    <alpha
        android:fromAlpha="1"
        android:duration="800"  //子类的设置的时间会替换动画集合的时间
        android:toAlpha="0.0"
        ></alpha>

</set>

¿Cómo implementar un total de tres animaciones en una vista? Cuando termina una animación, se ejecuta otra animación.

La animación de propiedades tiene un atributo de orden, pero la animación de vista se ejecuta en conjunto y no tiene ningún atributo de orden.

Entonces podemos pasar

Atributo startOffset a ejecutar.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <translate
        android:fromXDelta="0"
        android:toXDelta="200"
        android:duration="500"
        ></translate>
    <rotate
        android:startOffset="500"
        android:fromDegrees="0"
        android:toDegrees="180"
        android:pivotX="100%"
        android:pivotY="50%"
        android:duration="500"
        ></rotate>

    <alpha
        android:startOffset="1000"
        android:fromAlpha="1"
        android:toAlpha="0.2"
        android:duration="500"
        ></alpha>


</set>

diseñoAnimación

layoutAnimation actúa en todos los grupos de vistas. Cuando se especifica esta animación para este grupo de vistas, todos los demás subelementos tendrán este efecto de animación cuando aparezcan. layoutAnimation no se refiere a una animación separada, sino a un medio. También se puede ver como una animación de vista.

método de escritura xml

Cree un archivo de tipo layoutAnimation en la carpeta anim.

lyanimation.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/slide_1"   
    android:animationOrder="normal"
    android:delay="0.5"
    >
</layoutAnimation>

animation //引用的view动画
animationOrder //子元素执行动画的顺序,有三种选项:normal、reverse和random,其中normal表示顺
序显示,即排在前面的子元素先开始播放入场动画;reverse表示逆向显示,即排在后面的
子元素先开始播放入场动画;random则是随机播放入场动画。
delay //表示子元素开始动画的时间延迟,比如子元素入场动画的时间周期为300ms,那么0.5
表示每个子元素都需要延迟150ms才能播放入场动画。总体来说,第一个子元素延迟
150ms开始播放入场动画,第2个子元素延迟300ms开始播放入场动画,依次类推。

 diapositiva_1.xml

<?xml version="1.0" encoding="utf-8"?>
<set
    android:duration="300"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<translate
    android:fromXDelta="-100%"
    android:toXDelta="0"
    ></translate>
</set>

Referenciado por android:layoutAnimation="@anim/lyanimation" en ViewGroup.

 <LinearLayout
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:id="@+id/tv_click_12"
        android:layout_marginBottom="@dimen/dp_300"
        android:layoutAnimation="@anim/lyanimation" //引用
        android:layout_height="wrap_content">

        <TextView
            android:background="@drawable/img"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_marginTop="@dimen/dp_30"
            android:layout_height="100px"></TextView>
        <TextView
            android:layout_marginTop="@dimen/dp_30"
            android:background="@drawable/img_1"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_height="100px"></TextView>
        <TextView
            android:layout_marginTop="@dimen/dp_30"
            android:background="@drawable/img_2"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_height="100px"></TextView>
        <TextView
            android:layout_marginTop="@dimen/dp_30"
            android:background="@drawable/img_3"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_height="100px"></TextView>
    </LinearLayout>
Establecer en código

Tenga en cuenta que esta es la animación de salida. Si viewGroup ya está visible, no tendrá ningún efecto si configura esta animación a través del evento de clic.

        val tv_click_12 = findViewById<LinearLayout>(R.id.tv_click_12);//获得viewGroup
 
     
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_1) //加载view动画
val LayoutAnimationController = LayoutAnimationController(loadAnimation).apply { //创建LayoutAnimationController
 delay = 0.5f
order = LayoutAnimationController.ORDER_NORMAL
            }
            tv_click_12.layoutAnimation = LayoutAnimationController  //设置
      

El efecto es como se muestra en la figura:

Efecto de cambio de actividad 

El salto de actividad tiene un efecto de animación predeterminado, pero también podemos personalizar esta animación. Principalmente a través

public void overridePendingTransition(int enterAnim, int exitAnim) { 
    ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), 
            enterAnim, exitAnim); 
}

Por aquí. Este método debe llamarse después de startActivity(intent) o Finish() para que surta efecto.

enterAnim : la identificación del recurso de animación requerida cuando se abre la Actividad ;
exitAnim : la identificación del recurso de animación requerida cuando se suspende la actividad .
El cambio de fragmentos también se puede animar. Dado que Fragment es una clase recientemente introducida en API 11, por razones de compatibilidad
Para capacitancia, necesitamos usar el paquete de compatibilidad support-v4 . En este caso, podemos usar FragmentTransaction.
Método setCustomAnimations () para agregar animaciones de conmutación. Esta animación de cambio debe ser una animación de Ver . La razón por la cual
La animación de propiedades no se puede utilizar porque la animación de propiedades también se introdujo recientemente en API 11 . ¿Existen otras formas de dar Actividad y
Fragment agrega animaciones de cambio, pero la mayoría de ellas tienen problemas de compatibilidad y no se pueden usar en versiones inferiores, por lo que no tienen
Tiene un alto valor de uso, por lo que no los presentaré uno por uno aquí.

animación de cuadro

La animación de cuadros reproduce un conjunto de imágenes predefinidas en secuencia, similar a la reproducción de películas. A diferencia de la animación de vista, el sistema proporciona una clase AnimationDrawable para usar la animación de fotogramas. AnimationDrawable pertenece a Drawable, así que haga clic derecho directamente en la carpeta dibujable -> nuevo -> archivo de recursos dibujable ->

Crear archivo xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"  oneshot = tru表示执行一遍,false是一直重复执行
    >
<item android:duration="200" android:drawable="@drawable/img"></item>
    <item android:duration="200" android:drawable="@drawable/img_1"></item>
    <item android:duration="200" android:drawable="@drawable/img_2"></item>
    <item android:duration="200" android:drawable="@drawable/img_3"></item>
</animation-list>

 Establecer vista para establecer el color de Beijing

Usado en código:

      val mAnimationDrawable = findViewById<View>(R.id.tv_click_11).background as AnimationDrawable
            mAnimationDrawable.start()

Eso es todo.

Animación de propiedades

La animación de propiedades extiende la animación de Ver y funciona en cualquier objeto, incluso en ningún objeto. La animación de propiedades no se limita a los cuatro cambios simples de traducción, escala, rotación y transparencia.

Las animaciones de propiedades incluyen ValueAnimator, ObjectAnimator y AnimtorSet. Con estos tres se pueden conseguir animaciones complejas.

Antes de comprender la animación de atributos, es necesario comprender dos clases:

interpolador interpolador, esta animación de vista también lo tiene. Evaluador TypeEvaluator

La función del interpolador es calcular el cambio porcentual del valor del atributo actual a lo largo del tiempo.

Android tiene varios interpoladores integrados

LinearInterpolator (interpolador lineal: animación uniforme)

AccelerateDecelerateInterpolator (interpolador de aceleración y desaceleración: la animación es lenta en ambos extremos y rápida en el medio)

DecelerateInterpolator (interpolador de desaceleración: la animación es cada vez más lenta)

La función de TypeEvaluator es calcular el valor del atributo modificado en función del porcentaje del cambio de atributo actual. El sistema tiene incorporado

IntEvaluator (para propiedades de números enteros)

FloatEvaluator (para propiedades de punto flotante)
ArgbEvaluator (para atributos de tipo de color)
Si nuestra animación de propiedades tiene como objetivo (no int,
float , Color ), debes personalizar el estimador de tipo .
Cómo personalizar el estimador:
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction,Integer startValue,Integer
endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue -startInt));
}
}

​​​​​​​

Animador de objetos

objectAnimator es para objetos. objectAnimator es una subclase de ValueAnimator.ObjectAnimator tiene los siguientes métodos importantes.

ObjectAnimator.ofInt()   
ObjectAnimator.ofFloat() 
ObjectAnimator.ofArgb() 
ObjectAnimator.ofObject() 

//android proporciona evaluadores predeterminados como int, float, argb, etc. Si usa ObjectAnimator.ofObject(), debe personalizar la evaluación dispositivo. Puede consultar este artículo Aprendizaje de animación de Android (3): Animación de propiedad personalizada - Jianshu

 
public static ObjectAnimator ofInt(Object target, String propertyName, int... value) { 
    ObjectAnimator anim = new ObjectAnimator(target, propertyName); 
    anim.setIntValues (valores); 
    devolver anim; 
}

objetivo: el objeto de la animación

propertyName: El nombre de la propiedad a cambiar, al ejecutar la animación se llamará continuamente al método set de esta propiedad.

int... valor: el valor del atributo cambia, es una matriz, por ejemplo: transparencia, de 0->1->0

Debido a que el principio de la animación de atributos es cambiar dinámicamente el valor del atributo a una cierta velocidad para lograr el efecto de la animación, se deben cumplir dos condiciones para configurar una animación de atributos:

1: Si configura la animación de atributo para un atributo AB, debe cumplirse. Este atributo tiene un método setAB, y si el valor inicial no está establecido, debe tener un método getAB. La animación del atributo obtendrá el valor inicial a través de esto método.

2. Los cambios en los valores de los atributos al realizar la animación de atributos deben reflejarse en la interfaz de usuario; de lo contrario, no tendrán ningún efecto.

por ejemplo: Cómo utilizar atributos para lograr los siguientes efectos.

Código de análisis: la imagen de la izquierda es un diseño expandido y contraído, podemos hacer que aparezca la imagen de la izquierda al hacer clic en el diseño rojo.

marginLeft cambia para lograr este efecto.

Según las dos condiciones que debe cumplir el atributo de animación, sabemos que el ImageView de la izquierda no tiene el atributo marginLeft. Entonces, ¿cómo resolver el problema de realizar animaciones en atributos que no cumplen las dos condiciones anteriores? La solución oficial es la siguiente:

  1. Proporcione una clase contenedora para que el objeto envuelva el objeto original. Si no existe tal atributo, proporcione este atributo indirectamente y proporcione los métodos get y set.
  2. Utilice ValueAnimator para monitorear el proceso de animación y cambiar las propiedades usted mismo.

 Código dinámico:

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:id="@+id/ln_content"
    tools:context=".AnimationActivity2">
    <TextView
        android:id="@+id/slide_s"
        android:layout_width="400px"
        android:text="点击显示全"
        android:background="@drawable/img_2"
        android:layout_height="match_parent"></TextView>
    <TextView
        android:text="点击展开和关闭"
        android:layout_width="50dp"
        android:id="@+id/click_button"
        android:background="@color/color_f74e00"
        android:layout_height="match_parent"></TextView>
    <HorizontalScrollView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="200dp"
            android:text="1"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="2"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:text="3"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="4"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="5"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="6"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="7"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:text="8"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:text="9"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
    </LinearLayout>


    </HorizontalScrollView>


</LinearLayout>
Código:
Implementado usando una clase contenedora:

Crear una clase contenedora: SlideWrapper

    class SlideWrapper(val mSlide: View) {
        private var marginLeft :Int  //提供这个属性
        get() {   //重新这个属性的get方法
            return (mSlide.layoutParams as LinearLayout.LayoutParams).leftMargin
        }
        set(value) {  //重写这个属性的set方法,满足属性值的改变会体验在ui效果上
          
            val apply = (mSlide.layoutParams as LinearLayout.LayoutParams).apply {
                leftMargin = value
            }
            mSlide.layoutParams = apply
        }

    }

var isExpand:Boolean = true  //定义一个字段记录展开和收起的状态
 val slideView  = SlideWrapper(slide_s)
findViewById<View>(R.id.click_button).setOnClickListener {
              it.isEnabled = false
              if (isExpand){
                  //这是属性动画
                  ObjectAnimator.ofInt(slideView,"marginLeft",-400).apply {
                      duration = 500
                    addListener(object :AnimatorListener{
                        override fun onAnimationStart(animation: Animator?) {
                        }

                        override fun onAnimationEnd(animation: Animator?) {
                            it.isEnabled = true
                            isExpand = false
                        }

                        override fun onAnimationCancel(animation: Animator?) {
                        }

                        override fun onAnimationRepeat(animation: Animator?) {
                        }

                    })
                      start()
                  }
              }  else{
              
                  ObjectAnimator.ofInt(slideView,"marginLeft",-400,0).apply {
                      duration =500
                      addListener(object:AnimatorListener{
                          override fun onAnimationStart(animation: Animator?) {
                          }

                          override fun onAnimationEnd(animation: Animator?) {
                              it.isEnabled = true
                              isExpand = true
                          }

                          override fun onAnimationCancel(animation: Animator?) {
                          }

                          override fun onAnimationRepeat(animation: Animator?) {
                          }

                      })
                      start()
                  }
              }
        }
Implementación del proceso de seguimiento de la animación utilizando ValueAnimator.

ValueAnimator en sí no actúa sobre ningún objeto, lo que significa que usarlo directamente no tiene ningún efecto. Puede animar un valor. Podemos monitorear su proceso de animación y modificar los valores de propiedad de nuestros objetos durante el proceso de animación. Esto también equivale a animar nuestros objetos.

  slide_s = findViewById<ImageView>(R.id.slide_s)
        findViewById<View>(R.id.click_button).setOnClickListener {
            it.isEnabled = false //防止动画没有执行完,触发点击事件
            if (isOpen){
                //执行关闭动画,我们监听从0到 -400的int值的变化
                ValueAnimator.ofInt(0,-400).apply {
                    duration = 500 //动画执行时间
                    //监听动画的每一帧
                    addUpdateListener(object :AnimatorUpdateListener{
                        override fun onAnimationUpdate(animation: ValueAnimator) {
                            val animatedValue = animation.animatedValue as Int //获得动画当前的值
                            val apply = (slide_s.layoutParams as LinearLayout.LayoutParams).apply {
                                leftMargin = animatedValue
                            }
                          
                        }

                    })
                    //监听动画的执行过程
                    addListener(object :AnimatorListener{
                        override fun onAnimationStart(animation: Animator?) {
                        }

                        override fun onAnimationEnd(animation: Animator?) {
                            it.isEnabled =true
                        }

                        override fun onAnimationCancel(animation: Animator?) {
                        }

                        override fun onAnimationRepeat(animation: Animator?) {
                        }

                    })
                    start()
                }


            }else{
                //执行打开动画
    ValueAnimator.ofInt(-400,0).apply {
        duration =500
        addUpdateListener(object :AnimatorUpdateListener{
            override fun onAnimationUpdate(animation: ValueAnimator) {
                val animatedValue = animation.animatedValue as Int //获得动画当前值
                val apply = (slide_s.layoutParams as LinearLayout.LayoutParams).apply {
                    leftMargin = animatedValue
                }
             
            }

        })

        addListener(object :AnimatorListener{
            override fun onAnimationStart(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                it.isEnabled =true
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationRepeat(animation: Animator?) {
            }

        })
        start()
    }
            }
        }

Aquí se utiliza AnimatorUpdateListener. Este oyente es especial. Monitorizará todo el proceso de animación. La animación se compone de muchos fotogramas. Cada vez que se reproduce un fotograma, se llamará a onAnimationUpdate una vez.

El efecto es el mismo.

Además de implementarse mediante código, la animación de atributos también se puede definir mediante XML. La animación de la propiedad debe definirse en

directorio res/animator/ , su sintaxis es la siguiente.
<set
android:ordering=["together" | "sequentially"]>
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>

</set>
属性动画的各种参数都比较好理解,在XML中可以定义ValueAnimator、ObjectAnimator以及AnimatorSet,其中<set>标签对应AnimatorSet,<Animator>标签对应
ValueAnimator,而<objectAnimator>则对应ObjectAnimator。<set>标签的android:ordering
属性有两个可选值:“together”和“sequentially”,其中“together”表示动画集合中的子动画
同时播放,“sequentially”则表示动画集合中的子动画按照前后顺序依次播放,
android:ordering属性的默认值是“together”。
对于<objectAnimator>标签的各个属性的含义,下面简单说明一下,对于<Animator>
标签这里就不再介绍了,因为它只是比<objectAnimator>少了一个android:propertyName属
性而已,其他都是一样的。
android:propertyName——表示属性动画的作用对象的属性的名称;
android:duration——表示动画的时长;
android:valueFrom——表示属性的起始值;
android:valueTo——表示属性的结束值;
android:startOffset——表示动画的延迟时间,当动画开始后,需要延迟多少毫秒才会
真正播放此动画;
android:repeatCount——表示动画的重复次数;
android:repeatMode——表示动画的重复模式;
android:valueType——表示android:propertyName所指定的属性的类型,
有“intType”和“floatType”两个可选项,分别表示属性的类型为整型和浮点型。另外,
如果android:propertyName所指定的属性表示的是颜色,那么不需要指定
android:valueType,系统会自动对颜色类型的属性做处理。
对于一个动画来说,有两个属性这里要特殊说明一下,一个是android:repeatCount,
它表示动画循环的次数,默认值为0,其中-1表示无限循环;另一个是
android:repeatMode,它表示动画循环的模式,有两个选项:“repeat”和“reverse”,分别表
示连续重复和逆向重复。连续重复比较好理解,就是动画每次都重新开始播放,而逆向重
复是指第一次播放完以后,第二次会倒着播放动画,第三次再重头开始播放动画,第四次
再倒着播放动画,如此反复

 

Supongo que te gusta

Origin blog.csdn.net/xueyoubangbang/article/details/132109140
Recomendado
Clasificación