react-native-navigation的迁移库

ViewController.java 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package com.reactnativenavigation.viewcontrollers;
  2. import android.app.Activity;
  3. import android.support.annotation.CallSuper;
  4. import android.support.annotation.CheckResult;
  5. import android.support.annotation.NonNull;
  6. import android.support.annotation.Nullable;
  7. import android.support.annotation.VisibleForTesting;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.view.ViewManager;
  11. import android.view.ViewTreeObserver;
  12. import com.reactnativenavigation.parse.Options;
  13. import com.reactnativenavigation.parse.params.Bool;
  14. import com.reactnativenavigation.parse.params.NullBool;
  15. import com.reactnativenavigation.presentation.FabOptionsPresenter;
  16. import com.reactnativenavigation.utils.CommandListener;
  17. import com.reactnativenavigation.utils.StringUtils;
  18. import com.reactnativenavigation.utils.Task;
  19. import com.reactnativenavigation.utils.UiUtils;
  20. import com.reactnativenavigation.viewcontrollers.stack.StackController;
  21. import com.reactnativenavigation.views.Component;
  22. public abstract class ViewController<T extends ViewGroup> implements ViewTreeObserver.OnGlobalLayoutListener {
  23. private Runnable onAppearedListener;
  24. private Bool waitForRender = new NullBool();
  25. public interface ViewVisibilityListener {
  26. /**
  27. * @return true if the event is consumed, false otherwise
  28. */
  29. boolean onViewAppeared(View view);
  30. /**
  31. * @return true if the event is consumed, false otherwise
  32. */
  33. boolean onViewDisappear(View view);
  34. }
  35. Options initialOptions;
  36. public Options options;
  37. private final Activity activity;
  38. private final String id;
  39. protected T view;
  40. @Nullable private ParentController<T> parentController;
  41. private boolean isShown;
  42. private boolean isDestroyed;
  43. private ViewVisibilityListener viewVisibilityListener = new ViewVisibilityListenerAdapter();
  44. protected FabOptionsPresenter fabOptionsPresenter;
  45. public ViewController(Activity activity, String id, Options initialOptions) {
  46. this.activity = activity;
  47. this.id = id;
  48. fabOptionsPresenter = new FabOptionsPresenter();
  49. this.initialOptions = initialOptions;
  50. options = initialOptions.copy();
  51. }
  52. public void setWaitForRender(Bool waitForRender) {
  53. this.waitForRender = waitForRender;
  54. }
  55. public void setOnAppearedListener(Runnable onAppearedListener) {
  56. this.onAppearedListener = onAppearedListener;
  57. }
  58. protected abstract T createView();
  59. public void setViewVisibilityListener(ViewVisibilityListener viewVisibilityListener) {
  60. this.viewVisibilityListener = viewVisibilityListener;
  61. }
  62. @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
  63. public void ensureViewIsCreated() {
  64. getView();
  65. }
  66. public boolean handleBack(CommandListener listener) {
  67. return false;
  68. }
  69. @CheckResult
  70. public Options resolveCurrentOptions() {
  71. return options;
  72. }
  73. @CheckResult
  74. public Options resolveCurrentOptions(Options defaultOptions) {
  75. return options.copy().withDefaultOptions(defaultOptions);
  76. }
  77. @CallSuper
  78. public void mergeOptions(Options options) {
  79. this.options = this.options.mergeWith(options);
  80. applyOptions(this.options);
  81. this.options.clearOneTimeOptions();
  82. }
  83. @CallSuper
  84. public void applyOptions(Options options) {
  85. }
  86. public void setDefaultOptions(Options defaultOptions) {
  87. }
  88. public Activity getActivity() {
  89. return activity;
  90. }
  91. protected void applyOnParentController(Task<ParentController> task) {
  92. if (parentController != null) task.run(parentController);
  93. }
  94. @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
  95. public ParentController getParentController() {
  96. return parentController;
  97. }
  98. public void setParentController(@NonNull final ParentController parentController) {
  99. this.parentController = parentController;
  100. }
  101. boolean performOnParentStack(Task<StackController> task) {
  102. if (parentController instanceof StackController) {
  103. task.run((StackController) parentController);
  104. return true;
  105. }
  106. if (this instanceof StackController) {
  107. task.run((StackController) this);
  108. return true;
  109. }
  110. return false;
  111. }
  112. void performOnParentStack(Task accept, Runnable reject) {
  113. if (!performOnParentStack(accept)) {
  114. reject.run();
  115. }
  116. }
  117. public T getView() {
  118. if (view == null) {
  119. if (isDestroyed) {
  120. throw new RuntimeException("Tried to create view after it has already been destroyed");
  121. }
  122. view = createView();
  123. view.getViewTreeObserver().addOnGlobalLayoutListener(this);
  124. }
  125. return view;
  126. }
  127. public void detachView() {
  128. ((ViewManager) view.getParent()).removeView(view);
  129. }
  130. public void attachView(ViewGroup parent, int index) {
  131. if (view.getParent() == null) parent.addView(view, index);
  132. }
  133. public String getId() {
  134. return id;
  135. }
  136. boolean isSameId(final String id) {
  137. return StringUtils.isEqual(this.id, id);
  138. }
  139. @Nullable
  140. public ViewController findControllerById(String id) {
  141. return isSameId(id) ? this : null;
  142. }
  143. public boolean containsComponent(Component component) {
  144. return getView().equals(component);
  145. }
  146. public void onViewWillAppear() {
  147. }
  148. @CallSuper
  149. public void onViewAppeared() {
  150. isShown = true;
  151. applyOptions(options);
  152. applyOnParentController(parentController -> {
  153. parentController.clearOptions();
  154. if (getView() instanceof Component) parentController.applyChildOptions(options, (Component) getView());
  155. });
  156. if (onAppearedListener != null) {
  157. onAppearedListener.run();
  158. onAppearedListener = null;
  159. }
  160. }
  161. public void onViewWillDisappear() {
  162. }
  163. @CallSuper
  164. public void onViewDisappear() {
  165. isShown = false;
  166. }
  167. @CallSuper
  168. public void destroy() {
  169. if (isShown) {
  170. isShown = false;
  171. onViewDisappear();
  172. }
  173. if (view instanceof Destroyable) {
  174. ((Destroyable) view).destroy();
  175. }
  176. if (view != null) {
  177. view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
  178. if (view.getParent() instanceof ViewGroup) {
  179. ((ViewManager) view.getParent()).removeView(view);
  180. }
  181. view = null;
  182. isDestroyed = true;
  183. }
  184. }
  185. @Override
  186. public void onGlobalLayout() {
  187. if (!isShown && isViewShown()) {
  188. if (!viewVisibilityListener.onViewAppeared(view)) {
  189. isShown = true;
  190. onViewAppeared();
  191. }
  192. } else if (isShown && !isViewShown()) {
  193. if (!viewVisibilityListener.onViewDisappear(view)) {
  194. isShown = false;
  195. onViewDisappear();
  196. }
  197. }
  198. }
  199. void runOnPreDraw(Task<T> task) {
  200. UiUtils.runOnPreDrawOnce(getView(), () -> task.run(getView()));
  201. }
  202. public abstract void sendOnNavigationButtonPressed(String buttonId);
  203. protected boolean isViewShown() {
  204. return !isDestroyed &&
  205. getView().isShown() &&
  206. view != null &&
  207. isRendered();
  208. }
  209. public boolean isRendered() {
  210. return view != null && (
  211. waitForRender.isFalseOrUndefined() ||
  212. !(view instanceof Component) ||
  213. ((Component) view).isRendered()
  214. );
  215. }
  216. void applyOnController(ViewController controller, Task<ViewController> task) {
  217. if (controller != null) task.run(controller);
  218. }
  219. }