FixFragmentNavigator.java 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package com.example.modifier;
  2. import android.content.Context;
  3. import android.os.Bundle;
  4. import android.util.Log;
  5. import android.view.View;
  6. import androidx.annotation.IdRes;
  7. import androidx.annotation.NonNull;
  8. import androidx.annotation.Nullable;
  9. import androidx.fragment.app.Fragment;
  10. import androidx.fragment.app.FragmentManager;
  11. import androidx.fragment.app.FragmentTransaction;
  12. import androidx.navigation.NavDestination;
  13. import androidx.navigation.NavOptions;
  14. import androidx.navigation.Navigator;
  15. import androidx.navigation.fragment.FragmentNavigator;
  16. import java.lang.reflect.Field;
  17. import java.util.ArrayDeque;
  18. import java.util.List;
  19. import java.util.Map;
  20. @Navigator.Name("fixFragment")
  21. public class FixFragmentNavigator extends FragmentNavigator {
  22. private final String TAG = "ReLoadFragmentNavictor";
  23. private final Context mContext;
  24. private final FragmentManager mFragmentManager;
  25. private final int mContainerId;
  26. String oldClassName = null;
  27. public FixFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) {
  28. super(context, manager, containerId);
  29. mContext = context;
  30. mFragmentManager = manager;
  31. mContainerId = containerId;
  32. }
  33. @Nullable
  34. @Override
  35. public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args, @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
  36. if (mFragmentManager.isStateSaved()) {
  37. Log.i(TAG, "Ignoring navigate() call: FragmentManager has already"
  38. + " saved its state");
  39. return null;
  40. }
  41. String className = destination.getClassName();
  42. if (className.equals(oldClassName)) {
  43. return null;
  44. }
  45. oldClassName = className;
  46. if (className.charAt(0) == '.') {
  47. className = mContext.getPackageName() + className;
  48. }
  49. Fragment frag = mFragmentManager.findFragmentByTag(className);
  50. if (null == frag) {
  51. //不存在,则创建
  52. frag = instantiateFragment(mContext, mFragmentManager, className, args);
  53. }
  54. frag.setArguments(args);
  55. final FragmentTransaction ft = mFragmentManager.beginTransaction();
  56. int enterAnim = navOptions != null ? navOptions.getEnterAnim() : -1;
  57. int exitAnim = navOptions != null ? navOptions.getExitAnim() : -1;
  58. int popEnterAnim = navOptions != null ? navOptions.getPopEnterAnim() : -1;
  59. int popExitAnim = navOptions != null ? navOptions.getPopExitAnim() : -1;
  60. if (enterAnim != -1 || exitAnim != -1 || popEnterAnim != -1 || popExitAnim != -1) {
  61. enterAnim = enterAnim != -1 ? enterAnim : 0;
  62. exitAnim = exitAnim != -1 ? exitAnim : 0;
  63. popEnterAnim = popEnterAnim != -1 ? popEnterAnim : 0;
  64. popExitAnim = popExitAnim != -1 ? popExitAnim : 0;
  65. ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim);
  66. }
  67. // ft.replace(mContainerId, frag);
  68. List<Fragment> fragments = mFragmentManager.getFragments();
  69. for (Fragment fragment : fragments) {
  70. ft.hide(fragment);
  71. }
  72. if (!frag.isAdded()) {
  73. ft.add(mContainerId, frag, className);
  74. }
  75. ft.show(frag);
  76. ft.setPrimaryNavigationFragment(frag);
  77. final @IdRes int destId = destination.getId();
  78. //通过反射获取mBackStack
  79. ArrayDeque<Integer> mBackStack;
  80. try {
  81. Field field = FragmentNavigator.class.getDeclaredField("mBackStack");
  82. field.setAccessible(true);
  83. mBackStack = (ArrayDeque<Integer>) field.get(this);
  84. } catch (Exception e) {
  85. e.printStackTrace();
  86. return null;
  87. }
  88. final boolean initialNavigation = mBackStack.isEmpty();
  89. final boolean isSingleTopReplacement = navOptions != null && !initialNavigation
  90. && navOptions.shouldLaunchSingleTop()
  91. && mBackStack.peekLast() == destId;
  92. boolean isAdded;
  93. if (initialNavigation) {
  94. isAdded = true;
  95. } else if (isSingleTopReplacement) {
  96. if (mBackStack.size() > 1) {
  97. mFragmentManager.popBackStack(
  98. generateBackStackName(mBackStack.size(), mBackStack.peekLast()),
  99. FragmentManager.POP_BACK_STACK_INCLUSIVE);
  100. ft.addToBackStack(generateBackStackName(mBackStack.size(), destId));
  101. }
  102. isAdded = false;
  103. } else {
  104. ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId));
  105. isAdded = true;
  106. }
  107. if (navigatorExtras instanceof Extras) {
  108. Extras extras = (Extras) navigatorExtras;
  109. for (Map.Entry<View, String> sharedElement : extras.getSharedElements().entrySet()) {
  110. ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue());
  111. }
  112. }
  113. ft.setReorderingAllowed(true);
  114. ft.commit();
  115. if (isAdded) {
  116. mBackStack.add(destId);
  117. return destination;
  118. } else {
  119. return null;
  120. }
  121. }
  122. //navigate需要打方法重复类直接复制过来就可以
  123. @NonNull
  124. private String generateBackStackName(int backStackIndex, int destId) {
  125. return backStackIndex + "-" + destId;
  126. }
  127. }