2012-06-20 14 views
38

Quiero establecer la visibilidad de los botones una vez finalizada la animación.Realizar la acción después de que finalice la animación de transacción de fragmento

Eso es lo que llama la animación:

android.support.v4.app.FragmentTransaction fAnimation = this.getActivity().getSupportFragmentManager().beginTransaction(); 
fAnimation.setCustomAnimations(android.R.anim.slide_in_left, R.anim.pull_out_to_left); 
if (this.isVisible()) { 
    fAnimation.hide(this); 
    fAnimation.commit(); 
} 

// code that will be executed when the fragment is gone (after the animation is over) 

¿Hay alguna manera de adjuntar un oyente saber cuando mi fragmento se ha ido?

Respuesta

13

Es necesario crear la subclase Fragment e invalidar onCreateAnimator, luego puede cargar esas animaciones de XML y adjuntar oyentes.

E.g.

public class MyFragment extends Fragment 
{ 
    @Override 
    public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) 
    { 
     final int animatorId = (enter) ? R.anim.in_anim : R.anim.out_anim; 
     final Animator anim = AnimatorInflater.loadAnimator(getActivity(), animatorId); 
     anim.addListener(new AnimatorListenerAdapter() 
     { 
      @Override 
      public void onAnimationStart(Animator animation) 
      { 
       ... 
      } 

      @Override 
      public void onAnimationEnd(Animator animation) 
      { 
       ... 
      } 
     }); 

     return anim; 
    }  
+0

Intenté esto, pero 'onCreateAnimation' nunca se llama. Estoy usando 'Fragment' del paquete de soporte v4 y no tiene' onCreateAnimatior', solo 'onCreateAnimation'. Hay alguna diferencia? – ffleandro

+0

No se ha notado antes, pero supongo que es porque los animadores son 3.0+ solamente. ¿Está configurando la transacción del fragmento correctamente como se muestra en http://stackoverflow.com/questions/4817900/android-fragments-and-animation? – nmw

+0

sí, 'FragmentManager fragmentManager = getActivity(). GetSupportFragmentManager(); FragmentTransaction ft = fragmentManager.beginTransaction(); ft.setCustomAnimations (R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right); ft.addToBackStack (null); ft.replace (R.id.tabContainer, fragmento); ft.commit(); fragmentManager.executePendingTransactions(); ' – ffleandro

51

los animadores que @nmw implementos en su respuesta se añadieron en el nivel API 11 y no va a funcionar con fragmentos que se aplica en la biblioteca de soporte Android.

Para escuchar eventos de animación Fragmento, extendí la clase de la biblioteca de soporte Fragment y hizo caso omiso de onCreateAnimation, adjuntando una AnimationListener personalizada para el objeto Animación devuelto:

public class MyFragment extends android.support.v4.app.Fragment { 

    private static final String TAG = "MyFragment"; 

    @Override 
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { 

     Animation anim = AnimationUtils.loadAnimation(getActivity(), nextAnim); 

     anim.setAnimationListener(new AnimationListener() { 

      @Override 
      public void onAnimationStart(Animation animation) { 
       Log.d(TAG, "Animation started."); 
       // additional functionality 
      } 

      @Override 
      public void onAnimationRepeat(Animation animation) { 
       Log.d(TAG, "Animation repeating."); 
       // additional functionality 
      } 

      @Override 
      public void onAnimationEnd(Animation animation) { 
       Log.d(TAG, "Animation ended."); 
       // additional functionality 
      } 
     }); 

     return anim; 
    } 
} 
+8

El oyente no se llama cuando enter es falso, porque FragmentManagerImpl establece su propio oyente. Devolverlo envuelto con un AnimationSet funciona. – sergio91pt

+0

@ sergio91pt ¿Podría explicar cómo? –

+7

@Sheikh Aman Basta con crear un nuevo AnimationSet, añadir la animación (que tiene su oyente enchufar) y devolver el conjunto. Esto simplemente permite a FragmentManagerImpl establecer otro oyente sin sobrepasar el suyo. – sergio91pt

6

La combinación de las respuestas anteriores aquí es una muestra que estoy usando con éxito con los fragmentos de la biblioteca de soporte.

Simplemente extienda el MenuFragment y configure el oyente para obtener una devolución de llamada de lo que se ejecutará después.

public class MenuFragment extends Fragment { 

private WeakReference<OnMenuClosedListener> onMenuClosedListener; 

@Override 
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { 
    Animation anim = null; 
    if (enter) { 
     anim = AnimationUtils.loadAnimation(getActivity(), R.anim.anim_slide_in_top); 
    } else { 
     anim = AnimationUtils.loadAnimation(getActivity(), R.anim.anim_menu_slide_out_top); 
     anim.setAnimationListener(new AnimationListener() { 
      @Override public void onAnimationStart(Animation animation) { 
      } 
      @Override public void onAnimationRepeat(Animation animation) { 
      } 
      @Override public void onAnimationEnd(Animation animation) { 
       onMenuClosed(); 
      } 
     }); 
    } 

    // NOTE: the animation must be added to an animation set in order for the listener 
    // to work on the exit animation 
    AnimationSet animSet = new AnimationSet(true); 
    animSet.addAnimation(anim); 

    return animSet; 
} 

private void onMenuClosed() { 
    if (this.onMenuClosedListener != null) { 
     OnMenuClosedListener listener = this.onMenuClosedListener.get(); 
     if (listener != null) { 
      listener.onMenuClosed(); 
     } 
    } 
} 

public void setOnMenuClosedListener(OnMenuClosedListener listener) { 
    this.onMenuClosedListener = new WeakReference<MenuFragment.OnMenuClosedListener>(listener); 
} 

/** 
* Callback for when the menu is closed. 
*/ 
public static interface OnMenuClosedListener { 

    public abstract void onMenuClosed(); 

} 

}

+0

he intentado añadir la animación a un 'AnimationSet', pero ninguna de las devoluciones de llamada onAnimation consigo llamado a la salida. – toobsco42

+0

funcionó para mí, solo agregué AnimationSet – Santacrab

0

que tenía que hacer esto en Xamarin. Mi situación era que necesitaba una devolución de llamada una vez que terminó la animación del fragmento. Así es como yo hice que funcionara sin ningún parpadeo (esto es C#/Xamarin):

public override Animation OnCreateAnimation(int transit, bool enter, int nextAnim) 
    { 
     Animation anim = base.OnCreateAnimation(transit, enter, nextAnim); 

     if (anim == null && nextAnim != 0) { 
      anim = AnimationUtils.LoadAnimation(Activity, nextAnim); 
     } 

     anim.SetAnimationListener(this); 
     return anim; 
    } 

    public void OnAnimationEnd(Animation animation) 
    { 
    } 

    public void OnAnimationRepeat(Animation animation) 
    { 
    } 

    public void OnAnimationStart(Animation animation) 
    { 
    } 

Nota:

fragmento
  • El padre tiene que aplicar Animation.IAnimationListener
  • Usted tiene que devolver un AnimationSet lo contrario el FragmentManager anulará su oyente y las devoluciones de llamada no se dispararán.
Cuestiones relacionadas