Skip to content

Commit 782bd08

Browse files
committed
Improve the stability of pop()/popTo(), #791
1 parent 59b649f commit 782bd08

File tree

5 files changed

+229
-171
lines changed

5 files changed

+229
-171
lines changed

fragmentation_core/src/main/java/android/support/v4/app/FragmentationMagician.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Created by YoKey on 16/1/22.
1515
*/
1616
public class FragmentationMagician {
17-
private static boolean sSupportLessThan25dot4 = false;
17+
public static boolean sSupportLessThan25dot4 = false;
1818

1919
static {
2020
Field[] fields = FragmentManagerImpl.class.getDeclaredFields();

fragmentation_core/src/main/java/me/yokeyword/fragmentation/SupportFragmentDelegate.java

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,33 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
118118
// Fix the overlapping BUG on pre-24.0.0
119119
processRestoreInstanceState(savedInstanceState);
120120
mAnimHelper = new AnimatorHelper(_mActivity.getApplicationContext(), mFragmentAnimator);
121+
122+
final Animation enter = getEnterAnim();
123+
if (enter == null) return;
124+
125+
getEnterAnim().setAnimationListener(new Animation.AnimationListener() {
126+
127+
@Override
128+
public void onAnimationStart(Animation animation) {
129+
mSupport.getSupportDelegate().mFragmentClickable = false; // 开启防抖动
130+
131+
mHandler.postDelayed(new Runnable() {
132+
@Override
133+
public void run() {
134+
mSupport.getSupportDelegate().mFragmentClickable = true;
135+
}
136+
}, enter.getDuration());
137+
}
138+
139+
@Override
140+
public void onAnimationEnd(Animation animation) {
141+
}
142+
143+
@Override
144+
public void onAnimationRepeat(Animation animation) {
145+
146+
}
147+
});
121148
}
122149

123150
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
@@ -550,7 +577,6 @@ private void processRestoreInstanceState(Bundle savedInstanceState) {
550577
}
551578

552579
private void fixAnimationListener(Animation enterAnim) {
553-
mSupport.getSupportDelegate().mFragmentClickable = false;
554580
// AnimationListener is not reliable.
555581
getHandler().postDelayed(mNotifyEnterAnimEndRunnable, enterAnim.getDuration());
556582
mSupport.getSupportDelegate().mFragmentClickable = true;
@@ -642,18 +668,25 @@ public FragmentActivity getActivity() {
642668
return _mActivity;
643669
}
644670

645-
public long getEnterAnimDuration() {
671+
private Animation getEnterAnim() {
646672
if (mCustomEnterAnim == Integer.MIN_VALUE) {
647673
if (mAnimHelper != null && mAnimHelper.enterAnim != null) {
648-
return mAnimHelper.enterAnim.getDuration();
674+
return mAnimHelper.enterAnim;
649675
}
650676
} else {
651677
try {
652-
return AnimationUtils.loadAnimation(_mActivity, mCustomEnterAnim).getDuration();
678+
return AnimationUtils.loadAnimation(_mActivity, mCustomEnterAnim);
653679
} catch (Exception e) {
654680
e.printStackTrace();
655681
}
682+
}
683+
return null;
684+
}
656685

686+
private long getEnterAnimDuration() {
687+
Animation enter = getEnterAnim();
688+
if (enter != null) {
689+
return enter.getDuration();
657690
}
658691
return NOT_FOUND_ANIM_TIME;
659692
}
@@ -674,7 +707,7 @@ public long getExitAnimDuration() {
674707
return NOT_FOUND_ANIM_TIME;
675708
}
676709

677-
public long getPopExitAnimDuration() {
710+
private long getPopExitAnimDuration() {
678711
if (mCustomPopExitAnim == Integer.MIN_VALUE) {
679712
if (mAnimHelper != null && mAnimHelper.popExitAnim != null) {
680713
return mAnimHelper.popExitAnim.getDuration();
@@ -690,6 +723,22 @@ public long getPopExitAnimDuration() {
690723
return NOT_FOUND_ANIM_TIME;
691724
}
692725

726+
@Nullable
727+
Animation getExitAnim() {
728+
if (mCustomExitAnim == Integer.MIN_VALUE) {
729+
if (mAnimHelper != null && mAnimHelper.exitAnim != null) {
730+
return mAnimHelper.exitAnim;
731+
}
732+
} else {
733+
try {
734+
return AnimationUtils.loadAnimation(_mActivity, mCustomExitAnim);
735+
} catch (Exception e) {
736+
e.printStackTrace();
737+
}
738+
}
739+
return null;
740+
}
741+
693742
interface EnterAnimListener {
694743
void onEnterAnimStart();
695744
}

fragmentation_core/src/main/java/me/yokeyword/fragmentation/SupportHelper.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.view.View;
88
import android.view.inputmethod.InputMethodManager;
99

10+
import java.util.ArrayList;
1011
import java.util.List;
1112

1213
/**
@@ -169,4 +170,85 @@ private static ISupportFragment getActiveFragment(FragmentManager fragmentManage
169170
}
170171
return parentFragment;
171172
}
173+
174+
/**
175+
* Get the topFragment from BackStack
176+
*/
177+
public static ISupportFragment getBackStackTopFragment(FragmentManager fragmentManager) {
178+
return getBackStackTopFragment(fragmentManager, 0);
179+
}
180+
181+
/**
182+
* Get the topFragment from BackStack
183+
*/
184+
public static ISupportFragment getBackStackTopFragment(FragmentManager fragmentManager, int containerId) {
185+
int count = fragmentManager.getBackStackEntryCount();
186+
187+
for (int i = count - 1; i >= 0; i--) {
188+
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
189+
Fragment fragment = fragmentManager.findFragmentByTag(entry.getName());
190+
if (fragment instanceof ISupportFragment) {
191+
ISupportFragment supportFragment = (ISupportFragment) fragment;
192+
if (containerId == 0) return supportFragment;
193+
194+
if (containerId == supportFragment.getSupportDelegate().mContainerId) {
195+
return supportFragment;
196+
}
197+
}
198+
}
199+
return null;
200+
}
201+
202+
@SuppressWarnings("unchecked")
203+
static <T extends ISupportFragment> T findBackStackFragment(Class<T> fragmentClass, String toFragmentTag, FragmentManager fragmentManager) {
204+
int count = fragmentManager.getBackStackEntryCount();
205+
206+
if (toFragmentTag == null) {
207+
toFragmentTag = fragmentClass.getName();
208+
}
209+
210+
for (int i = count - 1; i >= 0; i--) {
211+
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
212+
213+
if (toFragmentTag.equals(entry.getName())) {
214+
Fragment fragment = fragmentManager.findFragmentByTag(entry.getName());
215+
if (fragment instanceof ISupportFragment) {
216+
return (T) fragment;
217+
}
218+
}
219+
}
220+
return null;
221+
}
222+
223+
static List<Fragment> getWillPopFragments(FragmentManager fm, String targetTag, boolean includeTarget) {
224+
Fragment target = fm.findFragmentByTag(targetTag);
225+
List<Fragment> willPopFragments = new ArrayList<>();
226+
227+
List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fm);
228+
if (fragmentList == null) return willPopFragments;
229+
230+
int size = fragmentList.size();
231+
232+
int startIndex = -1;
233+
for (int i = size - 1; i >= 0; i--) {
234+
if (target == fragmentList.get(i)) {
235+
if (includeTarget) {
236+
startIndex = i;
237+
} else if (i + 1 < size) {
238+
startIndex = i + 1;
239+
}
240+
break;
241+
}
242+
}
243+
244+
if (startIndex == -1) return willPopFragments;
245+
246+
for (int i = size - 1; i >= startIndex; i--) {
247+
Fragment fragment = fragmentList.get(i);
248+
if (fragment != null) {
249+
willPopFragments.add(fragmentList.get(i));
250+
}
251+
}
252+
return willPopFragments;
253+
}
172254
}

0 commit comments

Comments
 (0)