123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- package com.reactnativenavigation.screens;
-
- import android.support.annotation.Nullable;
- import android.support.v7.app.AppCompatActivity;
- import android.util.Log;
- import android.view.View;
- import android.widget.RelativeLayout;
- import android.widget.RelativeLayout.LayoutParams;
-
- import com.facebook.react.bridge.Callback;
- import com.reactnativenavigation.NavigationApplication;
- import com.reactnativenavigation.params.ContextualMenuParams;
- import com.reactnativenavigation.params.FabParams;
- import com.reactnativenavigation.params.ScreenParams;
- import com.reactnativenavigation.params.StyleParams;
- import com.reactnativenavigation.params.TitleBarButtonParams;
- import com.reactnativenavigation.params.TitleBarLeftButtonParams;
- import com.reactnativenavigation.utils.KeyboardVisibilityDetector;
- import com.reactnativenavigation.utils.Task;
- import com.reactnativenavigation.views.LeftButtonOnClickListener;
-
- import java.util.List;
- import java.util.Stack;
-
- public class ScreenStack {
- private static final String TAG = "ScreenStack";
-
- public interface OnScreenPop {
- void onScreenPopAnimationEnd();
- }
-
- private final AppCompatActivity activity;
- private RelativeLayout parent;
- private LeftButtonOnClickListener leftButtonOnClickListener;
- private Stack<Screen> stack = new Stack<>();
- private final KeyboardVisibilityDetector keyboardVisibilityDetector;
- private boolean isStackVisible = false;
- private final String navigatorId;
-
- public String getNavigatorId() {
- return navigatorId;
- }
-
- public ScreenStack(AppCompatActivity activity,
- RelativeLayout parent,
- String navigatorId,
- LeftButtonOnClickListener leftButtonOnClickListener) {
- this.activity = activity;
- this.parent = parent;
- this.navigatorId = navigatorId;
- this.leftButtonOnClickListener = leftButtonOnClickListener;
- keyboardVisibilityDetector = new KeyboardVisibilityDetector(parent);
- }
-
- public void pushInitialScreenWithAnimation(final ScreenParams initialScreenParams, LayoutParams params) {
- isStackVisible = true;
- pushInitialScreen(initialScreenParams, params);
- final Screen screen = stack.peek();
- screen.setOnDisplayListener(new Screen.OnDisplayListener() {
- @Override
- public void onDisplay() {
- screen.show(initialScreenParams.animateScreenTransitions);
- screen.setStyle();
- }
- });
- }
-
- public void pushInitialScreen(ScreenParams initialScreenParams, LayoutParams params) {
- Screen initialScreen = ScreenFactory.create(activity, initialScreenParams, leftButtonOnClickListener);
- initialScreen.setVisibility(View.INVISIBLE);
- addScreen(initialScreen, params);
- }
-
- public void push(final ScreenParams params, LayoutParams layoutParams) {
- Screen nextScreen = ScreenFactory.create(activity, params, leftButtonOnClickListener);
- final Screen previousScreen = stack.peek();
- if (isStackVisible) {
- pushScreenToVisibleStack(layoutParams, nextScreen, previousScreen);
- } else {
- pushScreenToInvisibleStack(layoutParams, nextScreen, previousScreen);
- }
- }
-
- private void pushScreenToVisibleStack(LayoutParams layoutParams, final Screen nextScreen, final Screen previousScreen) {
- nextScreen.setVisibility(View.INVISIBLE);
- addScreen(nextScreen, layoutParams);
- nextScreen.setOnDisplayListener(new Screen.OnDisplayListener() {
- @Override
- public void onDisplay() {
- nextScreen.show(nextScreen.screenParams.animateScreenTransitions, new Runnable() {
- @Override
- public void run() {
- parent.removeView(previousScreen);
- }
- });
- }
- });
- }
-
- private void pushScreenToInvisibleStack(LayoutParams layoutParams, Screen nextScreen, Screen previousScreen) {
- nextScreen.setVisibility(View.INVISIBLE);
- addScreen(nextScreen, layoutParams);
- parent.removeView(previousScreen);
- }
-
- private void addScreen(Screen screen, LayoutParams layoutParams) {
- addScreenBeforeSnackbarAndFabLayout(screen, layoutParams);
- stack.push(screen);
- }
-
- private void addScreenBeforeSnackbarAndFabLayout(Screen screen, LayoutParams layoutParams) {
- parent.addView(screen, parent.getChildCount() - 1, layoutParams);
- }
-
- public void pop(boolean animated) {
- pop(animated, null);
- }
-
- public void pop(final boolean animated, @Nullable final OnScreenPop onScreenPop) {
- if (!canPop()) {
- return;
- }
-
- final Screen toRemove = stack.pop();
- final Screen previous = stack.peek();
-
- if (keyboardVisibilityDetector.isKeyboardVisible()) {
- keyboardVisibilityDetector.setKeyboardCloseListener(new Runnable() {
- @Override
- public void run() {
- keyboardVisibilityDetector.setKeyboardCloseListener(null);
- swapScreens(animated, toRemove, previous, onScreenPop);
- }
- });
- keyboardVisibilityDetector.closeKeyboard();
- } else {
- swapScreens(animated, toRemove, previous, onScreenPop);
- }
- }
-
- private void swapScreens(boolean animated, final Screen toRemove, Screen previous, OnScreenPop onScreenPop) {
- readdPrevious(previous);
- previous.setStyle();
- toRemove.hide(animated, new Runnable() {
- @Override
- public void run() {
- toRemove.unmountReactView();
- parent.removeView(toRemove);
- }
- });
-
- if (onScreenPop != null) {
- onScreenPop.onScreenPopAnimationEnd();
- }
- }
-
- public Screen peek() {
- return stack.peek();
- }
-
- private void readdPrevious(Screen previous) {
- previous.setVisibility(View.VISIBLE);
- parent.addView(previous, 0);
- }
-
- public void popToRoot(boolean animated) {
- while (canPop()) {
- pop(animated);
- }
- }
-
- public void destroy() {
- for (Screen screen : stack) {
- screen.destroy();
- parent.removeView(screen);
- }
- stack.clear();
- }
-
- public boolean canPop() {
- return stack.size() > 1 && !isPreviousScreenAttachedToWindow();
- }
-
- private boolean isPreviousScreenAttachedToWindow() {
- Screen previousScreen = stack.get(stack.size() - 2);
- if (previousScreen.getParent() != null) {
- Log.w(TAG, "Can't pop stack. reason: previous screen is already attached");
- return true;
- }
- return false;
- }
-
- public void setScreenTopBarVisible(String screenInstanceId, final boolean visible, final boolean animate) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen param) {
- param.setTopBarVisible(visible, animate);
- }
- });
- }
-
- public void setScreenTitleBarTitle(String screenInstanceId, final String title) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen param) {
- param.setTitleBarTitle(title);
- }
- });
- }
-
- public void setScreenTitleBarSubtitle(String screenInstanceId, final String subtitle) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen param) {
- param.setTitleBarSubtitle(subtitle);
- }
- });
- }
-
- public void setScreenTitleBarRightButtons(String screenInstanceId, final String navigatorEventId, final List<TitleBarButtonParams> titleBarButtons) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen param) {
- param.setTitleBarRightButtons(navigatorEventId, titleBarButtons);
- }
- });
- }
-
- public void setScreenTitleBarLeftButton(String screenInstanceId, final String navigatorEventId, final TitleBarLeftButtonParams titleBarLeftButtonParams) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen param) {
- param.setTitleBarLeftButton(navigatorEventId, leftButtonOnClickListener, titleBarLeftButtonParams);
- }
- });
- }
-
- public void setFab(String screenInstanceId, final String navigatorEventId, final FabParams fabParams) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen param) {
- param.setFab(fabParams);
- }
- });
- }
-
- public void showContextualMenu(String screenInstanceId, final ContextualMenuParams params, final Callback onButtonClicked) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen screen) {
- screen.showContextualMenu(params, onButtonClicked);
- }
- });
- }
-
- public void dismissContextualMenu(String screenInstanceId) {
- performOnScreen(screenInstanceId, new Task<Screen>() {
- @Override
- public void run(Screen screen) {
- screen.dismissContextualMenu();
- }
- });
- }
-
- public StyleParams getCurrentScreenStyleParams() {
- return stack.peek().getStyleParams();
- }
-
- public boolean handleBackPressInJs() {
- ScreenParams currentScreen = stack.peek().screenParams;
- if (currentScreen.overrideBackPressInJs) {
- NavigationApplication.instance.getEventEmitter().sendNavigatorEvent("backPress", currentScreen.getNavigatorEventId());
- return true;
- }
- return false;
- }
-
- private void performOnScreen(String screenInstanceId, Task<Screen> task) {
- if (stack.isEmpty()) {
- return;
- }
-
- for (Screen screen : stack) {
- if (screen.getScreenInstanceId().equals(screenInstanceId)) {
- task.run(screen);
- return;
- }
- }
- }
-
- public void show() {
- isStackVisible = true;
- stack.peek().setStyle();
- stack.peek().setVisibility(View.VISIBLE);
- }
-
- public void hide() {
- isStackVisible = false;
- stack.peek().setVisibility(View.INVISIBLE);
- }
- }
|