33import android .animation .Animator ;
44import android .animation .AnimatorInflater ;
55import android .animation .ValueAnimator ;
6- import android .app .Fragment ;
76import android .content .res .Resources ;
7+ import android .util .Log ;
88
99import java .lang .reflect .Field ;
1010
1111/**
12- * ChildFragment fixes a critical view bug where child fragments are sometimes removed from the screen
12+ * Fragment fixes an animation bug where child fragments are sometimes removed from the screen
1313 * before their parents are removed from the screen.
1414 * More Info: http://stackoverflow.com/questions/14900738/nested-fragments-disappear-during-transition-animation
1515 * Created by Mark Salpeter on 9/20/16.
1616 */
17- public class ChildFragment extends Fragment {
17+ public class Fragment extends android . app . Fragment {
1818
19- public static String TAG = ChildFragment .class .getSimpleName ();
19+ public static String TAG = Fragment .class .getSimpleName ();
2020
2121 /**
2222 * sDefaultChildAnimationDuration is an arbitrary, but reasonable transition duration we can use if
2323 * reflection fails to obtain the parent Fragment next animation id
2424 */
2525 private static final int sDefaultChildAnimationDuration = 1000 ;
2626
27- @ Override public Animator onCreateAnimator (int transit , boolean enter , int nextAnim ) {
2827
29- // if a child fragment is being removed because its parent is being removed
30- // return a fake animator that lasts the duration of the parent's animator
31- Fragment removingParentFragment = getRemovingParent (getParentFragment ());
32- if (!enter && removingParentFragment != null ) {
33- // This is a workaround for the bug where child fragments disappear when
34- // the parent is removed (as all children are first removed from the parent)
35- // See https://code.google.com/p/android/issues/detail?id=55228
36- long duration = getNextAnimatiorDuration (removingParentFragment );
37- return ValueAnimator .ofFloat (0 , 1 ).setDuration (duration );
28+ /**
29+ * onCreateAnimator is overridden to fix the following animation bug:
30+ * http://stackoverflow.com/questions/14900738/nested-fragments-disappear-during-transition-animation
31+ */
32+ @ Override public Animator onCreateAnimator (int transit , boolean enter , int nextAnim ) {
33+ if (!enter ) {
34+ android .app .Fragment removingParentFragment = getRemovingParentFragment ();
35+ if (removingParentFragment != null ) {
36+ return ValueAnimator .ofFloat (0f , 1f ).setDuration (getNextAnimatorDuration (removingParentFragment ));
37+ }
3838 }
39-
40- // inflate the animator
41- Animator animator = null ;
42- try {
43- animator = AnimatorInflater .loadAnimator (getActivity (), nextAnim );
44- } catch (Exception e ) {}
45-
46- return animator ;
39+ return super .onCreateAnimator (transit , enter , nextAnim );
4740 }
4841
4942 /**
50- * getRemovingParent returns the first fragment or parent fragment that is removing r null if it can't find one
43+ * getRemovingParentFragment returns the first fragment or parent fragment that is removing r null if it can't find one
5144 */
52- private static Fragment getRemovingParent (Fragment fragment ) {
45+ private android .app .Fragment getRemovingParentFragment () {
46+ android .app .Fragment fragment = getParentFragment ();
5347 while (fragment != null ) {
5448 if (fragment .isRemoving ()) {
49+ Log .v (TAG , fragment .toString () + " is removing" );
5550 return fragment ;
5651 }
5752 fragment = fragment .getParentFragment ();
@@ -63,21 +58,29 @@ private static Fragment getRemovingParent(Fragment fragment) {
6358 * getNextAnimationDuration returns the "mNextAnim" animators duration
6459 * TODO: this needs a bug fix, but its not mission critical unless people are adding fragment transition
6560 */
66- private static long getNextAnimatiorDuration ( Fragment fragment ) {
61+ private static long getNextAnimatorDuration ( android . app . Fragment fragment ) {
6762 try {
6863
6964 // attempt to get the resource ID of the next animation that will be applied to the given fragment.
70- Field nextAnimField = Fragment .class .getDeclaredField ("mNextAnim" );
65+ Field nextAnimField = android . app . Fragment .class .getDeclaredField ("mNextAnim" );
7166 nextAnimField .setAccessible (true );
72- int nextAnimResource = nextAnimField .getInt (fragment );
67+ int nextAnimResourceID = nextAnimField .getInt (fragment );
68+
69+ Log .v (TAG , "nextAnimResourceID: " + nextAnimResourceID );
70+ if (nextAnimResourceID < 1 ) {
71+ return sDefaultChildAnimationDuration ;
72+ }
7373
7474 // load the animator
75- Animator nextAnim = AnimatorInflater .loadAnimator (fragment .getActivity (), nextAnimResource );
75+ Animator nextAnim = AnimatorInflater .loadAnimator (fragment .getActivity (), nextAnimResourceID );
76+
77+ Log .v (TAG , "nextAnim.getDuration(): " + nextAnim .getDuration ());
7678
7779 // return its duration
7880 return (nextAnim == null || nextAnim .getDuration () < 0 ) ? sDefaultChildAnimationDuration : nextAnim .getDuration ();
7981
8082 } catch (NoSuchFieldException |IllegalAccessException |Resources .NotFoundException ex ) {
83+ Log .e (TAG , ex .getMessage (), ex );
8184 return sDefaultChildAnimationDuration ;
8285 }
8386 }
0 commit comments