Android: ¿Cómo podemos backport withEndAction a versiones anteriores, con ayuda de Nueve Androides Antiguos

Estoy trabajando en algo que requiere alrededor de 10 animaciones para ser jugado uno tras otro, pero hay algunas condiciones que se verifican al final de cada animación, por lo que no puedo utilizar animación set o setStartDelay.

Me pareció muy fácil de hacer en Jelly Bean con los nuevos métodos de que es withEndAction mientras lo estaba haciendo como un experimento, pero ahora tengo que aplicarlo en una aplicación con minSdk 10.

Estoy usando Nine Old Android y funciona muy bien, pero usar setListner es muy difícil y crea código que es difícil de mantener durante 10 animaciones consecutivas.

Así que estaba pensando, la creación de un adaptador que hereda de nueve androides de edad y yo podría añadir withEndAction función que ejecuta el runnable?

¿Puede alguien guiarme sobre cómo hacer eso, y hay alguna mejor manera de hacer esto?

Gracias

He utilizado setListener

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { viewPropertyAnimator.setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { doSomething(); } }); } else { viewPropertyAnimator.withEndAction(new Runnable() { @Override public void run() { doSomething(); } }); } 

Ahora puede utilizar ViewCompat y añadir cualquier animación que desee.

 ViewCompat.animate(yourView).scaleY(3).withEndAction(yourRunnable).start(); 

Hay dos opciones que puedo pensar en:

  1. Crea tu propia piscina de animación usando un patrón de fachada (éste puede ser mucho trabajo)
  2. Obtener el código fuente del ADT y modificarlo. Aquí está si usted no puede encontrarlo: http://pastebin.com/9nCPC4aR . ViewPropertyAnimatorCompat (algo como ViewPropertyAnimatorCompat ) en su propio paquete. La clase no parece tener mucho acoplamiento con otras cosas de Android por lo que debe funcionar como es 🙂
  3. UPDATE: aquí hay otra opción, una cola de animación. Similar a la primera idea, pero un poco más sencillo:

Código:

 public class AnimationQueue extends LinkedList<Animation> implements AnimationListener { private View mView; public static AnimationQueue ready(Animation... animations) { AnimationQueue queue = new AnimationQueue(); for (Animation animation : animations) { queue.add(animation); } return queue; } public AnimationQueue steady(View view) { mView = view; return this; } public void go() { Animation animation = poll(); animation.setAnimationListener(this); mView.startAnimation(animation); } @Override public void onAnimationEnd(Animation animation) { go(); } @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } } 

Uso:

 AnimationQueue.ready(anim1, anim2, anim3).steady(view).go(); 

Aclamaciones

Mi Solución También estaba usando el fantástico nineoldandroids

En lugar de

 starsBig[4].animate().rotation(3600).setDuration(2000).withEndAction(runnable) 

yo si

 animate(starsBig[4]).rotationBy(3600).setDuration(2010); this.runOnUiThread(new Runnable() { public void run() { for (int i = 0; i < 5; i++) { starReset(stars[i]); starReset(starsBig[i]); } } }); 

Funcionó bien para una animación

Creo que tengo mejor solución:

  view.animate().setDuration(2000).alpha(0); //timAnimDelay.purge(); timAnimDelay.schedule(new TimerTask() { @Override public void run() { // on UI thread runOnUiThread(new Runnable() { @Override public void run() { // here animation } }); } // delay start } , 2000); timAnimDelay.purge(); 

Básicamente, para que su código sea más legible, puede utilizar el construido en AnimatorListenerAdapter para guardarlo del desorden de clase interno anónimo. Incluso puede abstraerlo más para que se vea como withEndAction como este:

 import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.Application; import android.support.v4.view.ViewPropertyAnimatorListener; import android.view.View; public class AnimatorActionListener extends AnimatorListenerAdapter { public enum ActionType { START, END; } final private ActionType type; final private Runnable action; public AnimatorActionListener(Runnable action, ActionType type) { this.action = action; this.type = type; } @Override public void onAnimationEnd(Animator animation) { if (type == ActionType.END) { action.run(); } } @Override public void onAnimationStart(Animator animation) { if (type == ActionType.START) { action.run(); } } } 

Y entonces el uso se convierte en:

  view.animate()./*...some parameters...*/.setListener(new AnimatorActionListener(new Runnable() { @Override public void run() { // do stuff } }, ActionType.END)); // or ActionType.START 

Y para aquellos que deben usar la plataforma construida en las funciones cuando hay una ( withStartAction, withEndAction ), simplemente coloque el código de comprobación de SDK en AnimatorActionListener también para guardar la clase de cliente de los desordenes.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.