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
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:
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>
Obtener la animación en código java.
animationDrawable = (AnimationDrawable) img.getBackground();
Usa esta animación
animationDrawable.start(); //开启动画
animationDrawable.stop(); //停止动画
2. método de código java
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);
- 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 etiqueta2. Código xml y descripción del atributo: (Crear directorio anim en res, nuevo archivo xml en anim)
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,完全透明-完全不透明
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%就是以图像的 中心为中轴点
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坐标
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,表示偶数次显示动画时会做方向相反的运动!
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.
RotateAnimation
RotateAnimation rotateAnimation = new RotateAnimation(0, 360); rotateAnimation.setRepeatCount(1); rotateAnimation.setRepeatMode(Animation.REVERSE); rotateAnimation.setDuration(2000); mImageView.startAnimation(rotateAnimation);
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);
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 detranslationX()
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
View
métodos de operación reales correspondientes a los métodos se muestran en la siguiente figura:Como se puede ver en la figura,
View
cada método de corresponde aViewPropertyAnimator
dos métodos de, uno de los cuales tiene-By
el sufijo, por ejemplo,View.setTranslationX()
corresponde a los dos métodosViewPropertyAnimator.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 gradualmentetranslationX(100)
mediante animación , y significa que el valor de aumenta gradualmente mediante animación .View
translationX
100
translationXBy(100)
View
translationX
100
Comprensión de la imagen: si
-By
no 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-By
este 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
- Si es un control personalizado, debe agregar el método
setter
/ ;getter
- Úselo para
ObjectAnimator.ofXXX()
crearObjectAnimator
un objeto; (debe tener los métodos setter y getter correspondientes)- 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 llamadaEl sistema proporciona nueve diferenciadores predeterminados de la siguiente manera:
AccelerateDecelerateInterpolator: este es el valor predeterminado
Interpolator
3. Configure el oyente:
El método para configurar un oyente es ligeramente diferente
ViewPropertyAnimator
al 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á.ObjectAnimator
ViewPropertyAnimator
setListener()
setUpdateListener()
setUpdate]Listener(null)
ObjectAnimator
addListener()
addUpdateListener()
removeUpdateListener()
Además, dado que
ObjectAnimator
admite pausar usandopause()
el método, también admiteaddPauseListener()
/ y tiene el método único and , que puede configurar un monitoreo único del inicio o final de la animación.removePauseListener()
ViewPropertyAnimator
withStartAction(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.AnimatorListener
Hay 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 estableceAnimatorListener
, se llamará aonAnimationCancel()
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
ViewPropertyAnimator
no admite la duplicación, este métodoViewPropertyAnimator
equivale 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
,ValueAnimator
que esObjectAnimator
la clase principal yViewPropertyAnimator
la implementación interna de, por lo que este parámetro es en realidadViewPropertyAnimator
el que está dentroValueAnimator
(inconsistente con la instancia de ViewPropertyAnimator), oObjectAnimator
es 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
ViewPropertyAnimator
exclusivos de . Hay dos diferencias principales entre ellos y el /set/addListener()
en la devolución de llamada :onAnimationStart()
onAnimationEnd()
withStartAction(Runnable)
/withEndAction(Runnable)
es de un solo uso y se descarta automáticamente después de ejecutar la animación. Incluso si se reutilizaViewPropertyAnimator
para otras animaciones más adelante, las devoluciones de llamada configuradas con ellas no se volverán a llamar. Laset/addListener()
configuraciónAnimatorListener
es válida continuamente. Cuando la animación se ejecuta repetidamente, siempre se llamará la devolución de llamada.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. EstoAnimatorListener.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:
<?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.
PropertyValuesHolder
No es posible usarlo en este caso , porque si estos atributos se colocan en la misma animación, deben compartirInterpolator
una 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 paraofFloat()
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, debesTypeEvaluator
usarlo . Por ejemplo, cambiar el color, etc.Uso: Con la ayuda de
TypeEvaluator
la animación de atributos, puedeofObject()
animar atributos de tipos ilimitados a través de . El método es muy sencillo:
- Escribe uno personalizado para el atributo de destino.
TypeEvaluator
- Úselo
ofObject()
para crearAnimator
y completar los personalizadosTypeEvaluator
como 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:
- 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.
- 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.
- 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.)