Acerca del uso y resumen de la animación de cuadros, la animación de interpolación y la animación de atributos de Android. (Código fuente adjunto)

Nota: Hay mucho contenido, por lo que puede leerlo en partes y luego dividirlo en tres conferencias.

1. Resumen de animación de Android

1. Animación de cuadros

La animación de fotogramas en realidad simula efectos de animación reproduciendo imágenes continuamente.

Las siguientes son dos formas de lograrlo:

1. método de archivo xml

  1. Primero cree Animation_lufi.xml en dibujable

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="false">
        <item android:drawable="@drawable/image7"
            android:duration="200"/>
        <item android:drawable="@drawable/image8"
            android:duration="200"/>
        <item android:drawable="@drawable/image9"
            android:duration="200"/>
        <item android:drawable="@drawable/image10"
            android:duration="200"/>
    
    </animation-list>
    

    Puedes obtener una vista previa del efecto:

Insertar descripción de la imagen aquí

  1. Agregue animación_lufi.xml como fondo en la vista en el archivo de diseño

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
        tools:context=".MainActivity">
        <View
            android:id="@+id/image"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:background="@drawable/animation_lufi"    
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/end" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. Obtener la animación en código java.

    animationDrawable = (AnimationDrawable) img.getBackground();
    
  3. Usa esta animación

    animationDrawable.start(); //开启动画
    
    animationDrawable.stop(); //停止动画
    

2. método de código java

  1. En código java:

            animationDrawable = new AnimationDrawable();
            animationDrawable.addFrame(getResources().getDrawable(R.drawable.image7),250);
            animationDrawable.addFrame(getResources().getDrawable(R.drawable.image8),250);
            animationDrawable.addFrame(getResources().getDrawable(R.drawable.image9),250);
            animationDrawable.addFrame(getResources().getDrawable(R.drawable.image10),250);
            img.setBackground(animationDrawable);
    
    1. Otros usos permanecen sin cambios. Es solo que la forma de obtener la instancia es diferente de la forma de agregar el marco.

2. Animación entre interpolación

Los desarrolladores de animación interpolación solo necesitan especificar los "fotogramas clave" de inicio y fin de la animación, y el sistema calcula y completa los "fotogramas intermedios" de los cambios de animación.

1. Tipos de animaciones de interpolación

AlphaAnimation:: Efecto de degradado de transparencia, especifique la transparencia inicial y final al crear, así como la duración de la animación, el rango de cambio de transparencia (0,1), 0 es completamente transparente, 1 es completamente opaco; ¡etiqueta correspondiente <alpha/>!
ScaleAnimation: Efecto de gradiente de escala. Al crear, debe especificar las proporciones de escala inicial y final, así como el punto de referencia de escala y la duración de la animación; ¡ <scale/>etiqueta correspondiente!
TranslateAnimation: Efecto de gradiente de desplazamiento, especifique las posiciones inicial y final al crear y especifique la duración de la animación; ¡ <translate/>etiqueta correspondiente!
RotateAnimation: Efecto de gradiente de rotación. Al crear, especifique los ángulos de rotación inicial y final de la animación, así como la duración de la animación y el eje de rotación; <rotate/>etiquetas correspondientes
AnimationSet: El degradado combinado es una combinación de los degradados anteriores, correspondientes a <set/>la etiqueta

2. Código xml y descripción del atributo: (Crear directorio anim en res, nuevo archivo xml en anim)

(Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-leeching. Se recomienda guardar la imagen y cargarla directamente (img-4q5lhTok-1686710312405) (C:\Users\SW\AppData\Roaming\Typora\ imágenes-de-usuario-de-typora\ image-20230526154902325.png)]

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

  1. AlphaAnimation:: anim_alpha.xml

    <?xml version="1.0" encoding="utf-8"?>
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromAlpha="1.0"
        android:toAlpha="0.1"
        android:duration = "3000"
        />
    
    fromAlpha : 起始透明度
    toAlpha : 结束透明度
    透明度的范围为:0-1,完全透明-完全不透明
    
  2. ScaleAnimation:anim_scale.xml

    <?xml version="1.0" encoding="utf-8"?>
    <scale xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:fromXScale="0.2"
        android:toXScale="1.5"
        android:fromYScale="0.2"
        android:toYScale="1.5"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="2000"/>
    
    fromXScale/fromYScale:沿着X轴/Y轴缩放的起始比例
    toXScale/toYScale:沿着X轴/Y轴缩放的结束比例
    pivotX/pivotY:缩放的中轴点X/Y坐标,即距离自身左边缘的位置,比如50%就是以图像的 中心为中轴点
    
  3. TranslateAnimation: anim_translate.xml

    <?xml version="1.0" encoding="utf-8"?>
    <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="-320"
        android:duration="2000"/>
    
    fromXDelta/fromYDelta:动画起始位置的X/Y坐标
    toXDelta/toYDelta:动画结束位置的X/Y坐标
    
  4. RotateAnimation:anim_rotate.xml

    <?xml version="1.0" encoding="utf-8"?>
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromDegrees="0"
        android:toDegrees="129"
        android:duration="1000"
        android:repeatCount="1"
        android:repeatMode="reverse"/>
    
    fromDegrees/toDegrees:旋转的起始/结束角度
    
    repeatCount:旋转的次数,默认值为0,代表一次,假如是其他值,比如3,则旋转4次 另外,值为-1或者infinite时,表示动画永不停止
    
    repeatMode:设置重复模式,默认restart,但只有当repeatCount大于0或者infinite或-1时 才有效。还可以设置成reverse,表示偶数次显示动画时会做方向相反的运动!
    
    
  5. AnimationSet: De hecho, es una colección de varias animaciones (y varias animaciones comienzan a reproducirse al mismo tiempo)

    anim_set.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:shareInterpolator="true" >
        <scale
            android:duration="2000"
            android:fromXScale="0.2"
            android:fromYScale="0.2"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toXScale="1.5"
            android:toYScale="1.5" />
        <rotate
            android:duration="1000"
            android:fromDegrees="0"
            android:repeatCount="1"
            android:repeatMode="reverse"
            android:toDegrees="360" />
        <translate
            android:duration="2000"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="320"
            android:toYDelta="0" />
        <alpha
            android:duration="2000"
            android:fromAlpha="1.0"
            android:toAlpha="0.1" />
    </set>
    
    android:shareInterpolator="true" : 为true时,set中的所有动画都共享同一插值器。 为false时,需要为set中每个动画都设置单独的插值器  (Interpolator)
    

3. El código java carga la animación xml para obtener la instancia de animación e iniciarla.

                //利用AnimationUtils从xml中加载获取Animation实例
               Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.anim_alpha); 
               //调用view去开启动画 
               mImageView.startAnimation(animation);

Lo anterior es el código Java para cargar la animación anim_alpha.xml. Lo mismo para otras cosas

4. Cree directamente instancias de animación en Java.

  1. RotateAnimation

                    RotateAnimation rotateAnimation = new RotateAnimation(0, 360);
                    rotateAnimation.setRepeatCount(1);
                    rotateAnimation.setRepeatMode(Animation.REVERSE);
                    rotateAnimation.setDuration(2000);
                    mImageView.startAnimation(rotateAnimation);
    
  2. AnimationSet

                    Animation rotateAnimation = new RotateAnimation(0, -720, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                            RotateAnimation.RELATIVE_TO_SELF, 0.5f);
                    rotateAnimation.setDuration(2000);
                    Animation translateAnimation = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT, 0, TranslateAnimation.RELATIVE_TO_PARENT, 0.5f,
                            TranslateAnimation.RELATIVE_TO_PARENT, 0, TranslateAnimation.RELATIVE_TO_PARENT, 0.5f);
                    translateAnimation.setDuration(2000);
                    Animation scaleAnimation = new ScaleAnimation(0, 1.4f, 0, 1.4f, ScaleAnimation.RELATIVE_TO_SELF,
                            0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
                    scaleAnimation.setDuration(2000);
                    Animation alphaAnimation = new AlphaAnimation(0, 1);
                    alphaAnimation.setDuration(2000);
                    AnimationSet animationSet = new AnimationSet(true);
                    animationSet.addAnimation(rotateAnimation);
                    animationSet.addAnimation(translateAnimation);
                    animationSet.addAnimation(scaleAnimation);
                    animationSet.addAnimation(alphaAnimation);
                    animationSet.setDuration(4000);
                    animationSet.setFillAfter(false);
                    mImageView.startAnimation(animationSet);
    
  3. Lo mismo se aplica a otras animaciones.

5. Monitoreo de animación entre interpolación

Llame a setAnimationListener (escucha AnimationListener) del objeto de animación para configurar el oyente
           scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
     
     
                    @Override
                    public void onAnimationStart(Animation animation) {
     
     
                        Log.d(TAG, "onAnimationStart:  开始" );
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
     
     
                        Log.d(TAG, "onAnimationEnd:  结束");
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
     
     
                        Log.d(TAG, "onAnimationRepeat: 重复");
                    }
                });

​onAnimationStart (): Se llama cuando comienza la animación.

​onAnimtaionRepeat (): Se llama cuando la animación se reproduce repetidamente

​onAnimationEnd (): Se llama cuando finaliza la animación.

Si se trata de una animación que se repite dos veces, se llamará a onAnimtaionRepeat dos veces, pero el inicio y el final solo se llamarán una vez.

3. Animación de atributos

1. VerPropertyAnimator

1. uso

Es relativamente sencillo de utilizar: View.animate()seguido de translationX()otros métodos, la animación se ejecutará automáticamente. Por ejemplo:

            imageView.animate().translationYBy(-100).translationXBy(100).setDuration(3000)
                     .setInterpolator(new AccelerateDecelerateInterpolator()).start();

Los métodos específicos que se pueden seguir y los Viewmétodos de operación reales correspondientes a los métodos se muestran en la siguiente figura:

Insertar descripción de la imagen aquí

Como se puede ver en la figura, Viewcada método de corresponde a ViewPropertyAnimatordos métodos de, uno de los cuales tiene -Byel sufijo, por ejemplo, View.setTranslationX()corresponde a los dos métodos ViewPropertyAnimator.translationX()de y . ViewPropertyAnimator.translationXBy()El método con -By()el sufijo es la versión incremental del método, por ejemplo, significa que el valor de aumenta gradualmente translationX(100)mediante animación , y significa que el valor de aumenta gradualmente mediante animación .ViewtranslationX100translationXBy(100)ViewtranslationX100

Comprensión de la imagen: si -Byno se utiliza este método, después de hacer clic una vez para reproducir la animación, cuando la animación finalice (es decir, cuando el valor modificado haya alcanzado el valor final), la animación no se reproducirá cuando haga clic nuevamente para reproducir la animación. (porque se ha alcanzado el valor final), no volverá a cambiar). Sin embargo, si usas -Byeste método, la animación seguirá reproduciéndose si vuelves a hacer clic, porque cada vez que haces clic, las propiedades del método correspondiente aumentarán y se "moverá".

Por ejemplo:

imageView.animate().translationYBy(-100).translationX(100).start();

Cuando se hace clic por primera vez, tanto x como y se moverán. Después de eso, sólo y se moverá cada vez que hagas clic. Porque X ha alcanzado el valor final después de la primera reproducción e Y es -100 cada vez;

2. Monitoreo

setListener(new Animator.AnimatorListener() {
     
     
                     @Override
                     public void onAnimationStart(@NonNull Animator animation) {
     
     
                             Log.d(TAG, "onAnimationStart: 开始");
                     }

                     @Override
                     public void onAnimationEnd(@NonNull Animator animation) {
     
     
                             Log.d(TAG, "onAnimationEnd:   结束");
                     }

                     @Override
                     public void onAnimationCancel(@NonNull Animator animation) {
     
     
                             Log.d(TAG, "onAnimationCancel:  取消");
                     }

                     @Override
                     public void onAnimationRepeat(@NonNull Animator animation) {
     
     
                              Log.d(TAG, "onAnimationRepeat:  重复");
                         }
                     })

Los métodos anteriores se resumen más adelante.

2.Animador de objetos

Uso: código java

  1. Si es un control personalizado, debe agregar el método setter/ ;getter
  2. Úselo para ObjectAnimator.ofXXX()crear ObjectAnimatorun objeto; (debe tener los métodos setter y getter correspondientes)
  3. Utilice start()el método para realizar animaciones.
                animator =ObjectAnimator.ofFloat(imageView,"alpha",1f,0f,1f);
                animator.setDuration(5000); //过渡时间
                //动画延迟500ms执行
                animator.setStartDelay(500);
                //执行重复次数 +1
                animator.setRepeatCount(1);
                // 设置动画重复播放模式 RESTART -执行完一遍后重新执行
                // REVERSE -执行完一遍后 从末位置往前执行
                animator.setRepeatMode(ValueAnimator.REVERSE);
                animator.start();

Interpolador Interpolator: setInterpolator(Interpolator interpolator)configuración de llamada

El sistema proporciona nueve diferenciadores predeterminados de la siguiente manera:

Insertar descripción de la imagen aquí

AccelerateDecelerateInterpolator: este es el valor predeterminadoInterpolator

3. Configure el oyente:

El método para configurar un oyente es ligeramente diferente ViewPropertyAnimatoral de: usando el método and , puede configurar un oyente y, cuando desee eliminarlo, complete el valor nulo para eliminarlo; y use y para agregar uno o más oyentes, para eliminar el oyente, especifique el objeto que se eliminará.ObjectAnimatorViewPropertyAnimatorsetListener()setUpdateListener()setUpdate]Listener(null)ObjectAnimatoraddListener()addUpdateListener()removeUpdateListener()

Además, dado que ObjectAnimatoradmite pausar usando pause()el método, también admite addPauseListener()/ y tiene el método único and , que puede configurar un monitoreo único del inicio o final de la animación.removePauseListener()ViewPropertyAnimatorwithStartAction(Runnable)withEndAction(Runnable)

3.1 ViewPropertyAnimator.setListener() / ObjectAnimator.addListener()

Los nombres de estos dos métodos son diferentes y la cantidad de oyentes que se pueden configurar también es diferente, pero sus tipos de parámetros son los mismos AnimatorListener, por lo que son esencialmente los mismos. AnimatorListenerHay 4 métodos de devolución de llamada:

3.1.1 onAnimationStart (animación animada)

Este método se llama cuando la animación comienza a ejecutarse.

3.1.2 onAnimationEnd (animación animada)

Este método se llama cuando finaliza la animación.

3.1.3 onAnimationCancel (animación animada)

cancel()Este método se llama cuando la animación se cancela mediante el método.

Cabe señalar que incluso si se cancela la animación, onAnimationEnd()se seguirá llamando. Entonces, cuando se cancela la animación, si se establece AnimatorListener, se llamará a onAnimationCancel()ambos . Será llamado antes .onAnimationEnd()onAnimationCancel()onAnimationEnd()

3.1.4 onAnimationRepeat (animación animada)

Este método se llama cuando la animación se repite mediante setRepeatMode()el método / setRepeatCount()o .repeat()

Dado que ViewPropertyAnimatorno admite la duplicación, este método ViewPropertyAnimatorequivale a no válido.

                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     
     
                    @Override
                    public void onAnimationUpdate(@NonNull ValueAnimator animation) {
     
     
                        Log.d(TAG, "onAnimationUpdate: " + animation.getAnimatedValue());
                    }
                });
                animator.addPauseListener(new Animator.AnimatorPauseListener() {
     
     
                    @Override
                    public void onAnimationPause(@NonNull Animator animation) {
     
     
                        Log.d(TAG, "onAnimationPause: ");
                    }

                    @Override
                    public void onAnimationResume(@NonNull Animator animation) {
     
     
                        Log.d(TAG, "onAnimationResume: ");
                    }
                });
                animator.addListener(new Animator.AnimatorListener() {
     
     
                    @Override
                    public void onAnimationStart(@NonNull Animator animation) {
     
     
                        Log.d(TAG, "onAnimationStart: ");
                    }

                    @Override
                    public void onAnimationEnd(@NonNull Animator animation) {
     
     
                        Log.d(TAG, "onAnimationEnd: ");
                    }

                    @Override
                    public void onAnimationCancel(@NonNull Animator animation) {
     
     
                        Log.d(TAG, "onAnimationCancel: ");
                    }

                    @Override
                    public void onAnimationRepeat(@NonNull Animator animation) {
     
     
                        Log.d(TAG, "onAnimationRepeat: ");
                    }
                });

3.2 ViewPropertyAnimator.setUpdateListener() / ObjectAnimator.addUpdateListener()

Al igual que los dos métodos anteriores en 3.1, aunque estos dos métodos tienen diferentes nombres y números de oyentes configurables, su esencia es en realidad la misma y sus parámetros son los mismos AnimatorUpdateListener. Tiene solo un método de devolución de llamada: onAnimationUpdate(ValueAnimator animation).

3.2.1 onAnimationUpdate (animación ValueAnimator)

Este método se llama cuando se actualizan las propiedades animadas.

El parámetro del método es uno ValueAnimator, ValueAnimatorque es ObjectAnimatorla clase principal y ViewPropertyAnimatorla implementación interna de, por lo que este parámetro es en realidad ViewPropertyAnimatorel que está dentro ValueAnimator(inconsistente con la instancia de ViewPropertyAnimator), o ObjectAnimatores en sí mismo para (es decir, la instancia del parámetro del método de escucha es el mismo que el de llamada (sus instancias son las mismas).

3.3 ObjectAnimator.addPauseListener()

3.4 ViewPropertyAnimator.withStartAction/EndAction (ejecutable)

Estos dos métodos son ViewPropertyAnimatorexclusivos de . Hay dos diferencias principales entre ellos y el / set/addListener()en la devolución de llamada :onAnimationStart()onAnimationEnd()

  1. withStartAction(Runnable)/ withEndAction(Runnable)es de un solo uso y se descarta automáticamente después de ejecutar la animación. Incluso si se reutiliza ViewPropertyAnimatorpara otras animaciones más adelante, las devoluciones de llamada configuradas con ellas no se volverán a llamar. La set/addListener()configuración AnimatorListeneres válida continuamente. Cuando la animación se ejecuta repetidamente, siempre se llamará la devolución de llamada.
  2. withEndAction(Runnable)La devolución de llamada establecida solo se llamará cuando la animación finalice normalmente y no se ejecutará cuando se cancele la animación. Esto AnimatorListener.onAnimationEnd()es inconsistente con el comportamiento de .

4. Obtenga ObjectAnimator mediante el método xml

Debe crear un animador en res y luego crear un archivo xml en el animador:

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="alpha"
    android:valueFrom="1"
    android:valueTo="0"
    android:valueType="floatType" />

adquisición de código java:

               animator = (ObjectAnimator) AnimatorInflater.loadAnimator(MainActivity.this,R.animator.animator_alpha); //xml方式 <ObjectAnimator>标签代码 objectAnimator
               animator.setTarget(imageView); //xml方式,需要加个Target

Revisión: las animaciones interpoladas se cargan usando AnimationUtils.loadAnimation

Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.anim_alpha);

3.Animador de valor

ValueAnimator (animación de valor) realiza la animación controlando el cambio de valor y luego asignándolo manualmente a las propiedades del objeto.

Los métodos principales del código Java de ValueAnimator son los siguientes:

ValueAnimator ofFloat(float... values) // 浮点型数值
ValueAnimator  ofInt(int... values) // 整型数值
ValueAnimator  ofObject(TypeEvaluator evaluator, Object... values) // 自定义对象类型

Utilice código java para obtener ValueAnimator:

             anim = ValueAnimator.ofFloat(0f, 1f); 
             anim.setDuration(5000);
             anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     
     
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
     
     
                     float currentValue = (float) animation.getAnimatedValue();
                     Log.d("MainActivity", "cuurent value is " + currentValue);
                     imageView.setAlpha(currentValue);
                 }
             });
             anim.start();

Utilice xml para obtener ValueAnimator:

<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
 android:valueFrom="0f"
 android:valueTo="1f"
 android:valueType="floatType"
 />

2. Obtenga la instancia de ValueAnimator en código Java:

anim =(ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.animator_value); //xml方式 <animator>标签代表 ValueAnimator

4. Titular de valores de propiedad

PropertyValuesHolder Cambiar varias propiedades en la misma animación también puede entenderse como iniciar varias animaciones al mismo tiempo.

usar:

              PropertyValuesHolder alphaProper =  PropertyValuesHolder.ofFloat("alpha", 0.5f, 1f);
              PropertyValuesHolder scaleXProper = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f);
              PropertyValuesHolder scaleYProper = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f);
              PropertyValuesHolder translationXProper = PropertyValuesHolder.ofFloat("translationX", -100, 0);
              PropertyValuesHolder translationYProper = PropertyValuesHolder.ofFloat("translationY", -100, 0);
              PropertyValuesHolder rotationProper = PropertyValuesHolder.ofFloat("rotation", 0, 360);
              ValueAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageView, alphaProper,
                      scaleXProper, scaleYProper,translationXProper,translationYProper,rotationProper);
              animator.setDuration(5000);
              animator.setRepeatCount(2);
              animator.setRepeatMode(ValueAnimator.REVERSE);
              animator.start();
public static ObjectAnimator ofPropertyValuesHolder(Object target,    PropertyValuesHolder... values)  //方法
Uso avanzado: PropertyValuesHolders.ofKeyframe() divide la misma propiedad
             Keyframe keyframe1 = Keyframe.ofFloat(0f, 0);    //动画完成0,到达0
             Keyframe keyframe2 = Keyframe.ofFloat(1f, 100);  //动画完成100%到达100
             Keyframe keyframe = Keyframe.ofFloat(0.5f, 200); //动画完成50%到达200
             PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", keyframe1, keyframe, keyframe2);
             ObjectAnimator animator2 = ObjectAnimator.ofPropertyValuesHolder(imageView, holder);
             animator2.setDuration(2000);
             animator2.start();

5.Conjunto de animadores

AnimatorSet Se ejecutan varias animaciones juntas.

A veces, no solo necesita cambiar varias propiedades en una animación, sino que también necesita que varias animaciones funcionen juntas. Por ejemplo, cuando el tamaño del contenido se amplía de 0 a 100%, comienza a moverse. PropertyValuesHolderNo es posible usarlo en este caso , porque si estos atributos se colocan en la misma animación, deben compartir Interpolatoruna serie de configuraciones como la hora de inicio, hora de finalización, etc. de la animación, por lo que la animación no se puede ejecutar secuencialmente. .

Entonces se necesita AnimatorSet

               ObjectAnimator rotate = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);
               ObjectAnimator translationX = ObjectAnimator.ofFloat(imageView, "translationX", -100, 0);
               ObjectAnimator translationY = ObjectAnimator.ofFloat(imageView, "translationY", 0, -100);
               ObjectAnimator scaleX = ObjectAnimator.ofFloat(imageView, "scaleX", 0, 1f);
               ObjectAnimator scaleY = ObjectAnimator.ofFloat(imageView, "scaleY", 1, 0.5f);
               ObjectAnimator alpha = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f);
               animSet = new AnimatorSet();
               animSet.play(rotate)
                       .with(alpha)
                       .before(scaleX)
                       .after(scaleY)
                       .with(translationX)
                       .before(translationY);
               animSet.setDuration(2000);
               animSet.start();
Nota: El mismo nivel se jugará al mismo tiempo. Por ejemplo, si se configuran dos con, sin importar dónde se coloquen, se reproducirán al mismo tiempo que la animación transmitida por reproducción, similar a después y antes.

6.Evaluador TypeEvaluator

En cuanto a ObjectAnimator, se puede utilizar ofInt()para animar las propiedades de números enteros y para ofFloat()animar propiedades decimales. Estos dos tipos de atributos son los dos más utilizados para la animación de atributos, sin embargo, en el desarrollo real, existen otros tipos que se pueden utilizar para la animación de atributos. Cuando necesites animar propiedades de otros tipos, debes TypeEvaluatorusarlo . Por ejemplo, cambiar el color, etc.

Uso: Con la ayuda de TypeEvaluatorla animación de atributos, puede ofObject()animar atributos de tipos ilimitados a través de . El método es muy sencillo:

  1. Escribe uno personalizado para el atributo de destino.TypeEvaluator
  2. Úselo ofObject()para crear Animatory completar los personalizados TypeEvaluatorcomo parámetros.
ValueAnimator  ofObject(TypeEvaluator evaluator, Object... values)
ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)

Del código fuente del evaluador TypeEvaluator, podemos ver que la función de esta clase es decirle a la animación cómo pasar del valor inicial al valor final.
Hay varias clases en el código fuente de Android que implementan esta interfaz, que son algunos evaluadores predeterminados proporcionados por el sistema. Tomemos FloatEvaluator como ejemplo para ver su código de implementación.

public class FloatEvaluator implements TypeEvaluator<Number> {
     
     
    public Float evaluate(float fraction, Number startValue, Number endValue) {
     
     
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

De la implementación de FloatEvaluator, podemos ver que en el método de evaluación, el valor final se resta del valor inicial, se calcula la diferencia entre ellos y luego se multiplica por el coeficiente de la fracción, más el valor inicial, luego el valor de Se obtiene la animación actual.

PD: La fracción es el grado de finalización, cambiará continuamente de 0 a 1

TypeEvaluator personalizado: simplemente implemente TypeEvaluator y escriba un algoritmo personalizado.

Por ejemplo: escribe un estimador que cambie de color.

public class MyTypeEvaluator implements TypeEvaluator<String> {
     
     
    private int mCurrentRed = -1;
    private int mCurrentGreen = -1;
    private int mCurrentBlue = -1;
    @Override
    public String evaluate(float fraction, String startValue, String endValue) {
     
     
        Log.d("text", "evaluate: " + fraction);
        int startRed = Integer.parseInt(startValue.substring(1, 3), 16);
        int startGreen = Integer.parseInt(startValue.substring(3, 5), 16);
        int startBlue = Integer.parseInt(startValue.substring(5, 7), 16);
        int endRed = Integer.parseInt(endValue.substring(1, 3), 16);
        int endGreen = Integer.parseInt(endValue.substring(3, 5), 16);
        int endBlue = Integer.parseInt(endValue.substring(5, 7), 16);
        Log.d("TAG", "evaluate: " + startRed + "   " + startGreen + "    " + startBlue + "    "
         + endRed + "    " + endGreen + "   " +endBlue);
        // 初始化颜色的值
        if (mCurrentRed == -1) {
     
     
            mCurrentRed = startRed;
        }
        if (mCurrentGreen == -1) {
     
     
            mCurrentGreen = startGreen;
        }
        if (mCurrentBlue == -1) {
     
     
            mCurrentBlue = startBlue;
        }
        // 计算初始颜色和结束颜色之间的差值
        int redDiff = Math.abs(startRed - endRed);
        int greenDiff = Math.abs(startGreen - endGreen);
        int blueDiff = Math.abs(startBlue - endBlue);

        if (mCurrentRed != endRed) {
     
     
            mCurrentRed = getCurrentColor(startRed, endRed, redDiff, fraction);

        }
        if (mCurrentGreen != endGreen) {
     
     
            mCurrentGreen = getCurrentColor(startGreen, endGreen, greenDiff, fraction);

        }
        if (mCurrentBlue != endBlue) {
     
     
            mCurrentBlue = getCurrentColor(startBlue, endBlue,blueDiff, fraction);


        }
        Log.d("test", "evaluate: " + mCurrentRed + "    " + mCurrentGreen + "   "+mCurrentBlue);
        // 将计算出的当前颜色的值组装返回
        String currentColor = "#" + getHexString(mCurrentRed)
                + getHexString(mCurrentGreen) + getHexString(mCurrentBlue);
        return currentColor;
    }
    /**
     * 根据fraction值来计算当前的颜色。
     */
    private int getCurrentColor(int startColor, int endColor, int colorDiff, float fraction) {
     
     
        int currentColor;
        if (startColor > endColor) {
     
     
            currentColor = (int) (startColor - (fraction * colorDiff));
            if (currentColor <= endColor) {
     
     
                currentColor = endColor;
            }
        } else {
     
     
            currentColor = (int) (startColor + (fraction * colorDiff));
            if (currentColor >= endColor) {
     
     
                currentColor = endColor;
            }
        }
        return currentColor;
    }
    /**
     * 将10进制颜色值转换成16进制。
     */
    private String getHexString(int value) {
     
     
        String hexString = Integer.toHexString(value);
        if (hexString.length() == 1) {
     
     
            hexString = "0" + hexString;
        }
        return hexString;
    }
}

usar:

 ValueAnimator animator1 = ValueAnimator.ofObject( new MyTypeEvaluator(), "#123456", "#ABCDEF");
 animator1.setDuration(3000);
 animator1.start();

Vídeo de demostración de animación de propiedad: no público

Resumen de las diferencias entre animación de interpolación y animación de atributos:

  1. Limitación de objetos: la animación de interpolación de vista solo se puede usar en la vista, es decir, solo puede animar un botón, una vista de texto o incluso un diseño lineal u otros componentes heredados de la vista, pero no puede animar objetos que no sean de vista. En algunos casos, el efecto de animación es solo un determinado atributo y objeto de la vista en lugar de toda la vista; por ejemplo, si necesita cambiar dinámicamente el color de la vista, debe operar el atributo de color de la vista para lograrlo. el efecto de animación, en lugar de animar toda la vista.
  2. No cambia las propiedades de la Vista, solo cambia los efectos visuales: la animación de interpolación solo cambia los efectos visuales de la Vista sin cambiar realmente las propiedades de la Vista. Por ejemplo, mover el botón en la esquina superior izquierda de la pantalla a la esquina inferior derecha de la pantalla mediante una animación de interpolación no tiene ningún efecto. Hacer clic en la posición actual del botón (esquina inferior derecha de la pantalla) no tiene ningún efecto, porque el botón en realidad permanece en la esquina superior izquierda de la pantalla, y la animación de interpolación simplemente mueve el botón. Al dibujarlo en la esquina inferior derecha de la pantalla, solo cambia el efecto visual.
  3. Efecto de animación único: la animación interpolada solo puede cumplir requisitos de animación simples como traducción, rotación, escala y transparencia. La animación de propiedades puede utilizar estimadores para utilizar algoritmos personalizados para cambiar otras propiedades (como el color, etc.)

Dirección del proyecto: no pública

Supongo que te gusta

Origin blog.csdn.net/XJ200012/article/details/131198776
Recomendado
Clasificación