react-native-navigation的迁移库

ScreenStack.java 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package com.reactnativenavigation.views;
  2. import android.animation.LayoutTransition;
  3. import android.content.Context;
  4. import android.util.AttributeSet;
  5. import android.view.ViewGroup;
  6. import android.widget.FrameLayout;
  7. import com.facebook.react.ReactInstanceManager;
  8. import com.facebook.react.ReactRootView;
  9. import com.reactnativenavigation.activities.BaseReactActivity;
  10. import com.reactnativenavigation.core.RctManager;
  11. import com.reactnativenavigation.core.objects.Screen;
  12. import com.reactnativenavigation.utils.ReflectionUtils;
  13. import java.util.Stack;
  14. import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
  15. public class ScreenStack extends FrameLayout {
  16. private static final int DISAPPEAR_ANIMATION_DELAY = 200;
  17. private static class ScreenView {
  18. Screen screen;
  19. RctView view;
  20. public ScreenView(Screen screen, RctView view) {
  21. this.screen = screen;
  22. this.view = view;
  23. }
  24. }
  25. private final Stack<ScreenView> mStack = new Stack<>();
  26. private final ReactInstanceManager mReactInstanceManager = RctManager.getInstance().getReactInstanceManager();
  27. private BaseReactActivity mReactActivity;
  28. public ScreenStack(BaseReactActivity context) {
  29. super(context);
  30. init(context);
  31. }
  32. public ScreenStack(Context context, AttributeSet attrs) {
  33. super(context, attrs);
  34. init(context);
  35. }
  36. private void init(Context context) {
  37. mReactActivity = (BaseReactActivity) context;
  38. setLayoutTransition(new LayoutTransition());
  39. }
  40. public void push(Screen screen) {
  41. push(screen, null);
  42. }
  43. public void push(Screen screen, RctView.OnDisplayedListener onDisplayed) {
  44. RctView oldView = mStack.isEmpty() ? null : mStack.peek().view;
  45. RctView view = new RctView(mReactActivity, mReactInstanceManager, screen, onDisplayed);
  46. if (oldView != null) {
  47. addView(view, MATCH_PARENT, MATCH_PARENT);
  48. ReflectionUtils.setBooleanField(oldView.getReactRootView(), "mAttachScheduled", true);
  49. getLayoutTransition().setStartDelay(LayoutTransition.DISAPPEARING, DISAPPEAR_ANIMATION_DELAY);
  50. removeView(oldView);
  51. getLayoutTransition().setStartDelay(LayoutTransition.DISAPPEARING, 0);
  52. } else {
  53. addView(view, MATCH_PARENT, MATCH_PARENT);
  54. }
  55. mStack.push(new ScreenView(screen, view));
  56. }
  57. public Screen pop() {
  58. if (mStack.isEmpty() || getStackSize() == 1) {
  59. return null;
  60. }
  61. ScreenView popped = mStack.pop();
  62. addView(mStack.peek().view, 0);
  63. ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false);
  64. removeView(popped.view);
  65. return popped.screen;
  66. }
  67. public Screen popToRoot() {
  68. if (mStack.isEmpty() || getStackSize() <= 1) {
  69. return null;
  70. }
  71. ScreenView oldScreenView = null;
  72. while (getStackSize() > 1) {
  73. ScreenView popped = mStack.pop();
  74. ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false);
  75. removeView(popped.view);
  76. if (oldScreenView == null) {
  77. oldScreenView = popped;
  78. }
  79. }
  80. if (!mStack.isEmpty()) {
  81. addView(mStack.peek().view, 0);
  82. }
  83. return oldScreenView != null ? oldScreenView.screen : null;
  84. }
  85. public Screen resetTo(Screen screen) {
  86. return resetTo(screen, null);
  87. }
  88. public Screen resetTo(Screen screen, RctView.OnDisplayedListener onDisplayed) {
  89. RctView view = new RctView(mReactActivity, mReactInstanceManager, screen, onDisplayed);
  90. addView(view, MATCH_PARENT, MATCH_PARENT);
  91. ScreenView oldScreenView = null;
  92. if (!mStack.isEmpty()) {
  93. while (getStackSize() > 0) {
  94. ScreenView screenView = mStack.pop();
  95. ReflectionUtils.setBooleanField(screenView.view.getReactRootView(), "mAttachScheduled", false);
  96. removeView(screenView.view);
  97. if (oldScreenView == null) {
  98. oldScreenView = screenView;
  99. }
  100. }
  101. }
  102. // Add screen to stack after it's clear
  103. mStack.push(new ScreenView(screen, view));
  104. if (oldScreenView == null) {
  105. return null;
  106. }
  107. return oldScreenView.screen;
  108. }
  109. public boolean isEmpty() {
  110. return mStack.isEmpty();
  111. }
  112. public int getStackSize() {
  113. return mStack.size();
  114. }
  115. public Screen peek() {
  116. return mStack.peek().screen;
  117. }
  118. /**
  119. * Remove the ScreenStack from {@code parent} while preventing all child react views from getting unmounted
  120. */
  121. public void removeFromScreen(ViewGroup parent) {
  122. ReactRootView view = mStack.peek().view.getReactRootView();
  123. ReflectionUtils.setBooleanField(view, "mAttachScheduled", true);
  124. parent.removeView(this);
  125. }
  126. /**
  127. * Add ScreenStack to {@code parent}
  128. */
  129. public void addToScreen(ViewGroup parent) {
  130. ReactRootView view = mStack.peek().view.getReactRootView();
  131. ReflectionUtils.setBooleanField(view, "mAttachScheduled", false);
  132. parent.addView(this, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
  133. }
  134. }