Skip to content

Commit 3d5189d

Browse files
committed
cleaned up the fragment animation bug fix and provided some loging for potential bug fixes
1 parent 20de1a6 commit 3d5189d

File tree

2 files changed

+40
-34
lines changed

2 files changed

+40
-34
lines changed

fragment/src/main/java/com/marksalpeter/fragment/ContractFragment.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
package com.marksalpeter.fragment;
22

33
import android.app.Activity;
4-
import android.app.Fragment;
54

65
import java.lang.reflect.ParameterizedType;
76

87
/**
9-
* ContractFragment is a fragment whos parent fragment or parent activity must implement an interface
10-
* Created by Mark Salpeter. Original concepts taken from Jake Thwarton
8+
* ContractFragment is a fragment whos parent fragment or parent activity must implement the interface T
9+
* Created by Mark Salpeter. Original concepts taken from Jake Wharton
1110
* see https://gist.github.com/JakeWharton/2621173
1211
*/
13-
public abstract class ContractFragment<T> extends ChildFragment {
12+
public abstract class ContractFragment<T> extends Fragment {
1413

15-
public final static String TAG = ChildFragment.class.getSimpleName();
14+
public final static String TAG = Fragment.class.getSimpleName();
1615

1716
private T mContract;
1817

1918
@Override
2019
public void onAttach(Activity activity) {
21-
Fragment parentFragment = getParentFragment();
20+
android.app.Fragment parentFragment = getParentFragment();
2221
if (parentFragment != null && isContractImplemented(parentFragment.getClass())) {
2322
mContract = (T) getParentFragment();
2423
} else if (isContractImplemented(activity.getClass())) {
@@ -44,6 +43,10 @@ public void onDetach() {
4443
mContract = null;
4544
}
4645

46+
/**
47+
* getContract returns the interface of type T that must be
48+
* implemented on either the parent fragment or the parent activity
49+
*/
4750
public final T getContract() {
4851
return mContract;
4952
}

fragment/src/main/java/com/marksalpeter/fragment/ChildFragment.java renamed to fragment/src/main/java/com/marksalpeter/fragment/Fragment.java

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,50 @@
33
import android.animation.Animator;
44
import android.animation.AnimatorInflater;
55
import android.animation.ValueAnimator;
6-
import android.app.Fragment;
76
import android.content.res.Resources;
7+
import android.util.Log;
88

99
import 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

Comments
 (0)