Cómo lograr animaciones de transacciones de fragmentos suaves en Android

He trabajado principalmente con iOS y me he acostumbrado a las animaciones de cambio de pantalla muy fluidas y fluidas. Ahora estoy trabajando en una aplicación de Android y no puedo por la vida de mí obtener una transacción de fragmento suavemente añadir / reemplazar un fragmento.

Mi configuración es la siguiente: MainActivity tiene un FrameLayout para su xml que inmediatamente carga FragmentA en MainActivity la MainActivity . Mi aplicación luego procede a reemplazar el MainActivity de FrameLayout con FragmentB , FragmentC , ect. Así que mi aplicación completa tiene 1 actividad.

En clics de botón llamo a lo siguiente para agregar / reemplazar el fragmento actual:

  getFragmentManager() .beginTransaction() .setCustomAnimations(R.animator.slide_in, android.R.animator.fade_out, android.R.animator.fade_in, R.animator.slide_out) .addToBackStack(null) .add(R.id.fragment_1, fragment) .commit(); 

Slide_in.xml parece (slide_out.xml es obviamente lo contrario):

  <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:interpolator="@android:interpolator/linear" android:propertyName="xFraction" android:valueType="floatType" android:valueFrom="1.0" android:valueTo="0" android:duration="@android:integer/config_shortAnimTime" /> </set> 

Deslizándose dentro y fuera Estoy animando xFraction que he subclasificado LinearLayout para hacer así:

 public class SlidingLinearLayout extends LinearLayout { private float yFraction = 0; private float xFraction = 0; public SlidingLinearLayout(Context context) { super(context); } public SlidingLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private ViewTreeObserver.OnPreDrawListener preDrawListener = null; public void setYFraction(float fraction) { this.yFraction = fraction; if (getHeight() == 0) { if (preDrawListener == null) { preDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(preDrawListener); setYFraction(yFraction); return true; } }; getViewTreeObserver().addOnPreDrawListener(preDrawListener); } return; } float translationY = getHeight() * fraction; setTranslationY(translationY); } public float getYFraction() { return this.yFraction; } public void setXFraction(float fraction) { this.xFraction = fraction; if (getWidth() == 0) { if (preDrawListener == null) { preDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(preDrawListener); setXFraction(xFraction); return true; } }; getViewTreeObserver().addOnPreDrawListener(preDrawListener); } return; } float translationX = getWidth() * fraction; setTranslationX(translationX); } public float getxFraction() { return xFraction; } } 

Así que mi problema es la mayor parte del tiempo cuando inicialmente haga clic en un botón para agregar / reemplazar un fragmento, no tengo una animación que sólo una especie de pops en su lugar. Sin embargo más veces que no cuando presiono el botón de la parte posterior y el fragmento estallido de la backstack la animación se ejecuta según lo esperado. Siento que es un problema con la inicialización al tratar de animar. Cuando el fragmento está en la memoria y animado fuera de la pantalla hace mucho mejor que cuando se crea un nuevo fragmento y luego se anima a la pantalla. Estoy curioso si otros han experimentado esto y si es así cómo lo resolvieron.

Esta es una molestia que ha plagado mi experiencia de desarrollo de Android que realmente me gustaría poner a descansar! Cualquier ayuda sería muy apreciada. ¡Gracias!

En mi experiencia, si el fragmento está haciendo demasiado trabajo en la carga, entonces el sistema básicamente omitirá la animación de entrada y sólo mostrar el fragmento. En mi caso la solución era crear un oyente de animación en onCreateAnimation para esperar hasta que la animación de entrada terminara antes de hacer el trabajo intensivo del proceso que estaba causando que la animación se saltara.

 @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { if (nextAnim == 0) { return super.onCreateAnimation(transit, enter, nextAnim); } Animation anim = android.view.animation.AnimationUtils.loadAnimation(getContext(), nextAnim); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationEnd(Animation animation) { // Do any process intensive work that can wait until after fragment has loaded } @Override public void onAnimationRepeat(Animation animation) {} }); return anim; } 
  • ¿Qué capacidades de eliminación automática de overdraw Android proporciona?
  • Cómo utilizar el lector de PDF Radaee sdk
  • Consejos para mejorar la tasa de llenado de OpenGL ES en Android
  • Para eventos de Android, ¿por qué las sentencias switch son más comunes que if-else?
  • Métodos estáticos o Singletons rendimiento-sabio (Android)?
  • ¿Cómo obtener el contexto en el caso de prueba uiautomator?
  • Sencha Touch 2 - Desempeño de Android
  • Cuenta de simulacro en ActivityInstrumentationTestCase2
  • Recyclerview de Android vs ListView con el usuario
  • ¿Cómo probar la función de sincronización de ejecución en android?
  • Cómo detener la creación excesiva de objetos en los teléfonos Samsung?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.