overridependingtransition fragments example entre animations animaciones android animation fragment

android - fragments - overridependingtransition fragment



Fragmento de animación de transición perdida después del cambio de configuración (5)

Estoy insertando Fragmentos en la Actividad usando este código:

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); FragmentManager fm = getFragmentManager(); String tag = "simple"; Fragment fr = fm.findFragmentByTag(tag); if (fr == null) { SimpleFragment simpleFragment = new SimpleFragment(); FragmentTransaction transaction = fm.beginTransaction(); transaction.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out, android.R.animator.fade_in, android.R.animator.fade_out); transaction.add(R.id.main_layout, simpleFragment, tag); transaction.addToBackStack(tag); transaction.commit(); } }

El código de fragmentos es:

public class SimpleFragment extends ListFragment { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getView().setBackgroundColor(Color.YELLOW); } }

Cuando saco el fragmento de backstack a través del botón Atrás justo después del lanzamiento, todo está bien y puedo ver la animación de fundido. Pero si giro el dispositivo y presiono el botón Atrás, el fragmento desaparece sin animación.

¿Es este comportamiento de Android o estoy haciendo algo mal?

EDITAR: Parece que después de la rotación, FragmentManager no restauró las animaciones (ingreseAnim, exitAnim, popEnterAnim y popExitAnim) para BackStackEntry.

Volcado FragmentManager (sin rotación):

Active Fragments in 4087d668: #0: SimpleFragment{408883b0 #0 id=0x7f050000 simple} mFragmentId=#7f050000 mContainerId#=7f050000 mTag=simple mState=4 mIndex=0 mWho=android:fragment:0 mBackStackNesting=1 mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false mHidden=false mDetached=false mRetainInstance=false mRetaining=false mHasMenu=false mFragmentManager=FragmentManager{4087d668 in ListViewFragmentsActivity{4087d588}} mImmediateActivity=my.app.ListViewFragmentsActivity@4087d588 mActivity=my.app.ListViewFragmentsActivity@4087d588 mNextAnim=17498112 mContainer=android.widget.RelativeLayout@408876d8 mView=android.widget.FrameLayout@40888a70 Added Fragments: #0: SimpleFragment{408883b0 #0 id=0x7f050000 simple} Back Stack: #0: android.app.BackStackRecord@408884b8 mName=simple mIndex=0 mCommitted=true mEnterAnim=#10b0000 mExitAnim=#10b0001 Operations: Op #0: cmd=1 fragment=SimpleFragment{408883b0 #0 id=0x7f050000 simple} enterAnim=17498112 exitAnim=17498113 popEnterAnim=17498112 popExitAnim=17498113 Back Stack Indices: #0: android.app.BackStackRecord@408884b8 FragmentManager misc state: mCurState=5 mStateSaved=false mDestroyed=false

Volcado FragmentManager (después de la rotación):

Active Fragments in 40877f38: #0: SimpleFragment{40878858 #0 id=0x7f050000 simple} mFragmentId=#7f050000 mContainerId#=7f050000 mTag=simple mState=4 mIndex=0 mWho=android:fragment:0 mBackStackNesting=1 mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false mHidden=false mDetached=false mRetainInstance=false mRetaining=false mHasMenu=false mFragmentManager=FragmentManager{40877f38 in ListViewFragmentsActivity{40877e58}} mImmediateActivity=my.app.ListViewFragmentsActivity@40877e58 mActivity=my.app.ListViewFragmentsActivity@40877e58 mContainer=android.widget.RelativeLayout@4087ed50 mView=android.widget.FrameLayout@4087fc00 Added Fragments: #0: SimpleFragment{40878858 #0 id=0x7f050000 simple} Back Stack: #0: android.app.BackStackRecord@40878a78 mName=simple mIndex=0 mCommitted=false Operations: Op #0: cmd=1 fragment=SimpleFragment{40878858 #0 id=0x7f050000 simple} Back Stack Indices: #0: android.app.BackStackRecord@40878a78 FragmentManager misc state: mCurState=5 mStateSaved=false mDestroyed=false


Como solución para esto, puede usar los métodos onCreateAnimator / onCreateAnimation en sus fragmentos.

Por ejemplo, para la implementación de fragmentos nativos:

@Override public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { if (enter) { return AnimatorInflater.loadAnimator(getActivity(), R.animator.slide_in_top); } else { return AnimatorInflater.loadAnimator(getActivity(), R.animator.fade_out); } }

La misma técnica para apoyar fragmentos de biblioteca con Animación en su lugar. En este caso, también tiene más control sobre cómo le gustaría reproducir la animación dependiendo del estado del fragmento y / o argumentos.


De acuerdo, este es un error que también es un problema para la biblioteca nativa (no solo para la biblioteca de soporte).

La única solución alternativa que puedo sugerir es crear tu propia pila de respaldo y luego manejarla. Volver con tu propia implementación personalizada configurando la animación correcta a medida que retrocedes en tu propia pila.



Puede usar onCreateAnimation plus AnimationUtils para cada fragmento en lugar de transaction.setCustomAnimations (..). También para omitir la animación durante la restauración, tenga en cuenta sobre la bandera boleean.

@Override public void onCreate(@Nullable Bundle savedInstanceState) { mIsRestoring = savedInstanceState != null; ... } @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { if (mIsRestoring) { mIsRestoring = false; return null; } if (enter) { return AnimationUtils.loadAnimation(getContext(), R.anim.enter_from_right); } else { return AnimationUtils.loadAnimation(getContext(), R.anim.exit_to_left); } }


Una sugerencia alternativa para evitar este problema es descargar la fuente de la biblioteca de soporte y realizar el cambio que sugerí en el defecto ( http://code.google.com/p/android/issues/detail?id=25994 ). , por supuesto, esto significa mantener una copia de la biblioteca de soporte usted mismo y no poder usar el soporte nativo, sin embargo, eso depende de cuán importante es para usted este problema.