diff --git a/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.java b/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.java index 8400d65c06..1a9430dea5 100644 --- a/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.java +++ b/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.java @@ -12,15 +12,23 @@ public class LifecycleHelper { private final Map mViewToLifecycleMap = new HashMap<>(); - private final View.OnLayoutChangeListener mRegisterOnLayoutChange = - new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange( - View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) { - registerViewWithLifecycleOwner(view); - view.removeOnLayoutChangeListener(this); - } - }; + private final View.OnLayoutChangeListener mRegisterOnLayoutChange = new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange( + View view, + int i, + int i1, + int i2, + int i3, + int i4, + int i5, + int i6, + int i7 + ) { + registerViewWithLifecycleOwner(view); + view.removeOnLayoutChangeListener(this); + } + }; public static @Nullable Fragment findNearestScreenFragmentAncestor(View view) { ViewParent parent = view.getParent(); diff --git a/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.java b/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.java index 6fef32395a..656b651481 100644 --- a/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.java +++ b/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.java @@ -9,6 +9,7 @@ import java.util.List; public class RNScreensPackage implements ReactPackage { + @Override public List createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); @@ -17,10 +18,11 @@ public List createNativeModules(ReactApplicationContext reactConte @Override public List createViewManagers(ReactApplicationContext reactContext) { return Arrays.asList( - new ScreenContainerViewManager(), - new ScreenViewManager(), - new ScreenStackViewManager(), - new ScreenStackHeaderConfigViewManager(), - new ScreenStackHeaderSubviewManager()); + new ScreenContainerViewManager(), + new ScreenViewManager(), + new ScreenStackViewManager(), + new ScreenStackHeaderConfigViewManager(), + new ScreenStackHeaderSubviewManager() + ); } } diff --git a/android/src/main/java/com/swmansion/rnscreens/Screen.java b/android/src/main/java/com/swmansion/rnscreens/Screen.java index 470b8b77f1..f8894b4e5b 100644 --- a/android/src/main/java/com/swmansion/rnscreens/Screen.java +++ b/android/src/main/java/com/swmansion/rnscreens/Screen.java @@ -19,22 +19,26 @@ public class Screen extends ViewGroup { - private static final OnAttachStateChangeListener sShowSoftKeyboardOnAttach = - new OnAttachStateChangeListener() { - - @Override - public void onViewAttachedToWindow(View view) { - InputMethodManager inputMethodManager = - (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.showSoftInput(view, 0); - view.removeOnAttachStateChangeListener(sShowSoftKeyboardOnAttach); - } + private static final OnAttachStateChangeListener sShowSoftKeyboardOnAttach = new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View view) { + InputMethodManager inputMethodManager = (InputMethodManager) view + .getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.showSoftInput(view, 0); + view.removeOnAttachStateChangeListener(sShowSoftKeyboardOnAttach); + } + + @Override + public void onViewDetachedFromWindow(View view) {} + }; + + @Nullable + private ScreenFragment mFragment; + + @Nullable + private ScreenContainer mContainer; - @Override - public void onViewDetachedFromWindow(View view) {} - }; - private @Nullable ScreenFragment mFragment; - private @Nullable ScreenContainer mContainer; private ActivityState mActivityState; private boolean mTransitioning; private StackPresentation mStackPresentation = StackPresentation.PUSH; @@ -98,14 +102,15 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { final int height = b - t; final ReactContext reactContext = (ReactContext) getContext(); reactContext.runOnNativeModulesQueueThread( - new GuardedRunnable(reactContext) { - @Override - public void runGuarded() { - reactContext - .getNativeModule(UIManagerModule.class) - .updateNodeSize(getId(), width, height); - } - }); + new GuardedRunnable(reactContext) { + @Override + public void runGuarded() { + reactContext + .getNativeModule(UIManagerModule.class) + .updateNodeSize(getId(), width, height); + } + } + ); } } @@ -155,8 +160,9 @@ public void setTransitioning(boolean transitioning) { return; } super.setLayerType( - transitioning && !isWebViewInScreen ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, - null); + transitioning && !isWebViewInScreen ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, + null + ); } private boolean hasWebView(ViewGroup viewGroup) { @@ -296,7 +302,10 @@ public void setStatusBarStyle(String statusBarStyle) { mStatusBarStyle = statusBarStyle; if (getFragment() != null) { ScreenWindowTraits.setStyle( - this, getFragment().tryGetActivity(), getFragment().tryGetContext()); + this, + getFragment().tryGetActivity(), + getFragment().tryGetContext() + ); } } @@ -323,7 +332,10 @@ public void setStatusBarTranslucent(Boolean statusBarTranslucent) { mStatusBarTranslucent = statusBarTranslucent; if (getFragment() != null) { ScreenWindowTraits.setTranslucent( - this, getFragment().tryGetActivity(), getFragment().tryGetContext()); + this, + getFragment().tryGetActivity(), + getFragment().tryGetContext() + ); } } @@ -343,7 +355,10 @@ public void setStatusBarColor(Integer statusBarColor) { mStatusBarColor = statusBarColor; if (getFragment() != null) { ScreenWindowTraits.setColor( - this, getFragment().tryGetActivity(), getFragment().tryGetContext()); + this, + getFragment().tryGetActivity(), + getFragment().tryGetContext() + ); } } @@ -358,7 +373,7 @@ public void setStatusBarAnimated(Boolean statusBarAnimated) { public enum StackPresentation { PUSH, MODAL, - TRANSPARENT_MODAL + TRANSPARENT_MODAL, } public enum StackAnimation { @@ -373,13 +388,13 @@ public enum StackAnimation { public enum ReplaceAnimation { PUSH, - POP + POP, } public enum ActivityState { INACTIVE, TRANSITIONING_OR_BELOW_TOP, - ON_TOP + ON_TOP, } public enum WindowTraits { @@ -388,6 +403,6 @@ public enum WindowTraits { STYLE, TRANSLUCENT, HIDDEN, - ANIMATED + ANIMATED, } } diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.java b/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.java index 65ede6af12..ee0ccd9e00 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.java @@ -22,31 +22,38 @@ public class ScreenContainer extends ViewGroup { protected final ArrayList mScreenFragments = new ArrayList<>(); - protected @Nullable FragmentManager mFragmentManager; - private @Nullable FragmentTransaction mCurrentTransaction; - private @Nullable FragmentTransaction mProcessingTransaction; + @Nullable + protected FragmentManager mFragmentManager; + + @Nullable + private FragmentTransaction mCurrentTransaction; + + @Nullable + private FragmentTransaction mProcessingTransaction; + private boolean mNeedUpdate; private boolean mIsAttached; - private final ChoreographerCompat.FrameCallback mFrameCallback = - new ChoreographerCompat.FrameCallback() { - @Override - public void doFrame(long frameTimeNanos) { - updateIfNeeded(); - } - }; + private final ChoreographerCompat.FrameCallback mFrameCallback = new ChoreographerCompat.FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + updateIfNeeded(); + } + }; private boolean mLayoutEnqueued = false; - private final ChoreographerCompat.FrameCallback mLayoutCallback = - new ChoreographerCompat.FrameCallback() { - @Override - public void doFrame(long frameTimeNanos) { - mLayoutEnqueued = false; - measure( - MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY)); - layout(getLeft(), getTop(), getRight(), getBottom()); - } - }; - private @Nullable ScreenFragment mParentScreenFragment = null; + private final ChoreographerCompat.FrameCallback mLayoutCallback = new ChoreographerCompat.FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + mLayoutEnqueued = false; + measure( + MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY) + ); + layout(getLeft(), getTop(), getRight(), getBottom()); + } + }; + + @Nullable + private ScreenFragment mParentScreenFragment = null; public ScreenContainer(Context context) { super(context); @@ -75,8 +82,9 @@ public void removeView(View view) { // detect that in removeView as super.removeView causes the input view to un focus while keeping // the keyboard open). if (view == getFocusedChild()) { - ((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE)) - .hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + ( + (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE) + ).hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } super.removeView(view); } @@ -89,9 +97,9 @@ public void requestLayout() { mLayoutEnqueued = true; // we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current // looper loop instead of enqueueing the update in the next loop causing a one frame delay. - ReactChoreographer.getInstance() - .postFrameCallback( - ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mLayoutCallback); + ReactChoreographer + .getInstance() + .postFrameCallback(ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mLayoutCallback); } } @@ -104,9 +112,9 @@ protected void markUpdated() { mNeedUpdate = true; // enqueue callback of NATIVE_ANIMATED_MODULE type as all view operations are executed in // DISPATCH_UI type and we want the callback to be called right after in the same frame. - ReactChoreographer.getInstance() - .postFrameCallback( - ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mFrameCallback); + ReactChoreographer + .getInstance() + .postFrameCallback(ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mFrameCallback); } } @@ -165,8 +173,9 @@ private void setFragmentManager(FragmentManager fm) { private void setupFragmentManager() { ViewParent parent = this; // We traverse view hierarchy up until we find screen parent or a root view - while (!(parent instanceof ReactRootView || parent instanceof Screen) - && parent.getParent() != null) { + while ( + !(parent instanceof ReactRootView || parent instanceof Screen) && parent.getParent() != null + ) { parent = parent.getParent(); } // If parent is of type Screen it means we are inside a nested fragment structure. @@ -195,7 +204,8 @@ private void setupFragmentManager() { } if (!(context instanceof FragmentActivity)) { throw new IllegalStateException( - "In order to use RNScreens components your app's activity need to extend ReactFragmentActivity or ReactCompatActivity"); + "In order to use RNScreens components your app's activity need to extend ReactFragmentActivity or ReactCompatActivity" + ); } setFragmentManager(((FragmentActivity) context).getSupportFragmentManager()); } @@ -213,18 +223,19 @@ protected void tryCommitTransaction() { final FragmentTransaction transaction = mCurrentTransaction; mProcessingTransaction = transaction; mProcessingTransaction.runOnCommit( - new Runnable() { - @Override - public void run() { - if (mProcessingTransaction == transaction) { - // we need to take into account that commit is initiated with some other transaction - // while the previous one is still processing. In this case mProcessingTransaction - // gets overwritten and we don't want to set it to null until the second transaction - // is finished. - mProcessingTransaction = null; - } + new Runnable() { + @Override + public void run() { + if (mProcessingTransaction == transaction) { + // we need to take into account that commit is initiated with some other transaction + // while the previous one is still processing. In this case mProcessingTransaction + // gets overwritten and we don't want to set it to null until the second transaction + // is finished. + mProcessingTransaction = null; } - }); + } + } + ); mCurrentTransaction.commitAllowingStateLoss(); mCurrentTransaction = null; } @@ -266,8 +277,10 @@ private void removeMyFragments() { boolean hasFragments = false; for (Fragment fragment : mFragmentManager.getFragments()) { - if (fragment instanceof ScreenFragment - && ((ScreenFragment) fragment).mScreenView.getContainer() == this) { + if ( + fragment instanceof ScreenFragment && + ((ScreenFragment) fragment).mScreenView.getContainer() == this + ) { transaction.remove(fragment); hasFragments = true; } @@ -349,8 +362,10 @@ protected void performUpdate() { // detach screens that are no longer active Set orphaned = new HashSet<>(mFragmentManager.getFragments()); for (ScreenFragment screenFragment : mScreenFragments) { - if (getActivityState(screenFragment) == Screen.ActivityState.INACTIVE - && screenFragment.isAdded()) { + if ( + getActivityState(screenFragment) == Screen.ActivityState.INACTIVE && + screenFragment.isAdded() + ) { detachScreen(screenFragment); } orphaned.remove(screenFragment); diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.java b/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.java index 933e35282e..938f980c7f 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.java @@ -33,7 +33,8 @@ public enum ScreenLifecycleEvent { public ScreenFragment() { throw new IllegalStateException( - "Screen fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity."); + "Screen fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity." + ); } @SuppressLint("ValidFragment") @@ -69,11 +70,15 @@ public void onResume() { @Override public View onCreateView( - LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState + ) { FrameLayout wrapper = new FrameLayout(getContext()); - FrameLayout.LayoutParams params = - new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ); mScreenView.setLayoutParams(params); wrapper.addView(recycleView(mScreenView)); return wrapper; @@ -177,10 +182,9 @@ private void dispatchEvent(ScreenLifecycleEvent event, ScreenFragment fragment) default: throw new IllegalStateException("Tried to dispatch unknown event: " + event.toString()); } - ((ReactContext) screen.getContext()) - .getNativeModule(UIManagerModule.class) - .getEventDispatcher() - .dispatchEvent(lifecycleEvent); + ((ReactContext) screen.getContext()).getNativeModule(UIManagerModule.class) + .getEventDispatcher() + .dispatchEvent(lifecycleEvent); fragment.dispatchEventInChildContainers(event); } @@ -189,9 +193,11 @@ private void dispatchEventInChildContainers(ScreenLifecycleEvent event) { for (ScreenContainer sc : mChildScreenContainers) { if (sc.getScreenCount() > 0) { Screen topScreen = sc.getTopScreen(); - if (topScreen != null - && topScreen.getFragment() != null - && (topScreen.getStackAnimation() != Screen.StackAnimation.NONE || isRemoving())) { + if ( + topScreen != null && + topScreen.getFragment() != null && + (topScreen.getStackAnimation() != Screen.StackAnimation.NONE || isRemoving()) + ) { // we do not dispatch events in child when it has `none` animation // and we are going forward since then they will be dispatched in child via // `onCreateAnimation` of ScreenStackFragment @@ -221,12 +227,13 @@ public void onViewAnimationStart() { // practical way to fix this is delaying dispatching the appear events at the end of the // frame. UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - dispatchOnWillAppear(); - } - }); + new Runnable() { + @Override + public void run() { + dispatchOnWillAppear(); + } + } + ); } else { dispatchOnWillDisappear(); } @@ -239,12 +246,13 @@ public void onViewAnimationEnd() { if (isResumed()) { // See the comment in onViewAnimationStart for why this event is delayed. UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - dispatchOnAppear(); - } - }); + new Runnable() { + @Override + public void run() { + dispatchOnAppear(); + } + } + ); } else { dispatchOnDisappear(); } @@ -256,10 +264,9 @@ public void onDestroy() { ScreenContainer container = mScreenView.getContainer(); if (container == null || !container.hasScreen(this)) { // we only send dismissed even when the screen has been removed from its container - ((ReactContext) mScreenView.getContext()) - .getNativeModule(UIManagerModule.class) - .getEventDispatcher() - .dispatchEvent(new ScreenDismissedEvent(mScreenView.getId())); + ((ReactContext) mScreenView.getContext()).getNativeModule(UIManagerModule.class) + .getEventDispatcher() + .dispatchEvent(new ScreenDismissedEvent(mScreenView.getId())); } mChildScreenContainers.clear(); } diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.java b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.java index 372bb13bde..e5000a2d2c 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.java @@ -25,28 +25,26 @@ public class ScreenStack extends ScreenContainer { private final List drawingOps = new ArrayList<>(); private ScreenStackFragment mTopScreen = null; - private final FragmentManager.OnBackStackChangedListener mBackStackListener = - new FragmentManager.OnBackStackChangedListener() { - @Override - public void onBackStackChanged() { - if (mFragmentManager.getBackStackEntryCount() == 0) { - // when back stack entry count hits 0 it means the user's navigated back using hw back - // button. As the "fake" transaction we installed on the back stack does nothing we need - // to handle back navigation on our own. - dismiss(mTopScreen); - } - } - }; - - private final FragmentManager.FragmentLifecycleCallbacks mLifecycleCallbacks = - new FragmentManager.FragmentLifecycleCallbacks() { - @Override - public void onFragmentResumed(FragmentManager fm, Fragment f) { - if (mTopScreen == f) { - setupBackHandlerIfNeeded(mTopScreen); - } - } - }; + private final FragmentManager.OnBackStackChangedListener mBackStackListener = new FragmentManager.OnBackStackChangedListener() { + @Override + public void onBackStackChanged() { + if (mFragmentManager.getBackStackEntryCount() == 0) { + // when back stack entry count hits 0 it means the user's navigated back using hw back + // button. As the "fake" transaction we installed on the back stack does nothing we need + // to handle back navigation on our own. + dismiss(mTopScreen); + } + } + }; + + private final FragmentManager.FragmentLifecycleCallbacks mLifecycleCallbacks = new FragmentManager.FragmentLifecycleCallbacks() { + @Override + public void onFragmentResumed(FragmentManager fm, Fragment f) { + if (mTopScreen == f) { + setupBackHandlerIfNeeded(mTopScreen); + } + } + }; private boolean mRemovalTransitionStarted = false; private boolean isDetachingCurrentScreen = false; private boolean reverseLastTwoChildren = false; @@ -57,19 +55,24 @@ public ScreenStack(Context context) { } private static boolean isSystemAnimation(Screen.StackAnimation stackAnimation) { - return stackAnimation == Screen.StackAnimation.DEFAULT - || stackAnimation == Screen.StackAnimation.FADE - || stackAnimation == Screen.StackAnimation.NONE; + return ( + stackAnimation == Screen.StackAnimation.DEFAULT || + stackAnimation == Screen.StackAnimation.FADE || + stackAnimation == Screen.StackAnimation.NONE + ); } private static boolean isTransparent(ScreenStackFragment fragment) { - return fragment.getScreen().getStackPresentation() - == Screen.StackPresentation.TRANSPARENT_MODAL; + return ( + fragment.getScreen().getStackPresentation() == Screen.StackPresentation.TRANSPARENT_MODAL + ); } private static boolean needsDrawReordering(ScreenStackFragment fragment) { - return fragment.getScreen().getStackAnimation() == Screen.StackAnimation.SLIDE_FROM_BOTTOM - || fragment.getScreen().getStackAnimation() == Screen.StackAnimation.FADE_FROM_BOTTOM; + return ( + fragment.getScreen().getStackAnimation() == Screen.StackAnimation.SLIDE_FROM_BOTTOM || + fragment.getScreen().getStackAnimation() == Screen.StackAnimation.FADE_FROM_BOTTOM + ); } public void dismiss(ScreenStackFragment screenFragment) { @@ -142,10 +145,9 @@ public void onViewAppearTransitionEnd() { } private void dispatchOnFinishTransitioning() { - ((ReactContext) getContext()) - .getNativeModule(UIManagerModule.class) - .getEventDispatcher() - .dispatchEvent(new StackFinishTransitioningEvent(getId())); + ((ReactContext) getContext()).getNativeModule(UIManagerModule.class) + .getEventDispatcher() + .dispatchEvent(new StackFinishTransitioningEvent(getId())); } @Override @@ -163,18 +165,16 @@ protected void removeAllScreens() { @Override protected boolean hasScreen(ScreenFragment screenFragment) { - return super.hasScreen(screenFragment) && !mDismissed.contains(screenFragment); + return (super.hasScreen(screenFragment) && !mDismissed.contains(screenFragment)); } @Override protected void performUpdate() { - // When going back from a nested stack with a single screen on it, we may hit an edge case // when all screens are dismissed and no screen is to be displayed on top. We need to gracefully // handle the case of newTop being NULL, which happens in several places below ScreenStackFragment newTop = null; // newTop is nullable, see the above comment ^ - ScreenStackFragment visibleBottom = - null; // this is only set if newTop has TRANSPARENT_MODAL presentation mode + ScreenStackFragment visibleBottom = null; // this is only set if newTop has TRANSPARENT_MODAL presentation mode isDetachingCurrentScreen = false; // we reset it so the previous value is not used by mistake for (int i = mScreenFragments.size() - 1; i >= 0; i--) { @@ -204,8 +204,8 @@ protected void performUpdate() { // before, probably replace or reset was called, so we play the "close animation". // Otherwise it's open animation shouldUseOpenAnimation = - mScreenFragments.contains(mTopScreen) - || newTop.getScreen().getReplaceAnimation() != Screen.ReplaceAnimation.POP; + mScreenFragments.contains(mTopScreen) || + newTop.getScreen().getReplaceAnimation() != Screen.ReplaceAnimation.POP; stackAnimation = newTop.getScreen().getStackAnimation(); } else if (mTopScreen == null && newTop != null) { // mTopScreen was not present before so newTop is the first screen added to a stack @@ -234,20 +234,19 @@ protected void performUpdate() { switch (stackAnimation) { case SLIDE_FROM_RIGHT: getOrCreateTransaction() - .setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left); + .setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left); break; case SLIDE_FROM_LEFT: getOrCreateTransaction() - .setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right); + .setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right); break; case SLIDE_FROM_BOTTOM: getOrCreateTransaction() - .setCustomAnimations( - R.anim.rns_slide_in_from_bottom, R.anim.rns_no_animation_medium); + .setCustomAnimations(R.anim.rns_slide_in_from_bottom, R.anim.rns_no_animation_medium); break; case FADE_FROM_BOTTOM: getOrCreateTransaction() - .setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350); + .setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350); break; } } else { @@ -255,20 +254,19 @@ protected void performUpdate() { switch (stackAnimation) { case SLIDE_FROM_RIGHT: getOrCreateTransaction() - .setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right); + .setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right); break; case SLIDE_FROM_LEFT: getOrCreateTransaction() - .setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left); + .setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left); break; case SLIDE_FROM_BOTTOM: getOrCreateTransaction() - .setCustomAnimations( - R.anim.rns_no_animation_medium, R.anim.rns_slide_out_to_bottom); + .setCustomAnimations(R.anim.rns_no_animation_medium, R.anim.rns_slide_out_to_bottom); break; case FADE_FROM_BOTTOM: getOrCreateTransaction() - .setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom); + .setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom); break; } } @@ -286,10 +284,12 @@ protected void performUpdate() { } // animation logic end - if (shouldUseOpenAnimation - && newTop != null - && needsDrawReordering(newTop) - && visibleBottom == null) { + if ( + shouldUseOpenAnimation && + newTop != null && + needsDrawReordering(newTop) && + visibleBottom == null + ) { // When using an open animation in which two screens overlap (eg. fade_from_bottom or // slide_from_bottom), we want to draw the previous screen under the new one, // which is apparently not the default option. Android always draws the disappearing view @@ -333,14 +333,15 @@ && needsDrawReordering(newTop) } // when first visible screen found, make all screens after that visible getOrCreateTransaction() - .add(getId(), screen) - .runOnCommit( - new Runnable() { - @Override - public void run() { - top.getScreen().bringToFront(); - } - }); + .add(getId(), screen) + .runOnCommit( + new Runnable() { + @Override + public void run() { + top.getScreen().bringToFront(); + } + } + ); } } else if (newTop != null && !newTop.isAdded()) { getOrCreateTransaction().add(getId(), newTop); @@ -404,11 +405,11 @@ private void setupBackHandlerIfNeeded(ScreenStackFragment topScreen) { if (topScreen != firstScreen && topScreen.isDismissable()) { mFragmentManager - .beginTransaction() - .show(topScreen) - .addToBackStack(BACK_STACK_TAG) - .setPrimaryNavigationFragment(topScreen) - .commitAllowingStateLoss(); + .beginTransaction() + .show(topScreen) + .addToBackStack(BACK_STACK_TAG) + .setPrimaryNavigationFragment(topScreen) + .commitAllowingStateLoss(); mFragmentManager.addOnBackStackChangedListener(mBackStackListener); } } @@ -476,6 +477,7 @@ private DrawingOp obtainDrawingOp() { } private final class DrawingOp { + private Canvas canvas; private View child; private long drawingTime; diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.java b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.java index 483a3ecc73..3507876313 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.java @@ -34,7 +34,8 @@ public ScreenStackFragment(Screen screenView) { public ScreenStackFragment() { throw new IllegalStateException( - "ScreenStack fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity."); + "ScreenStack fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity." + ); } public void removeToolbar() { @@ -49,9 +50,10 @@ public void setToolbar(Toolbar toolbar) { mAppBarLayout.addView(toolbar); } mToolbar = toolbar; - AppBarLayout.LayoutParams params = - new AppBarLayout.LayoutParams( - AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT); + AppBarLayout.LayoutParams params = new AppBarLayout.LayoutParams( + AppBarLayout.LayoutParams.MATCH_PARENT, + AppBarLayout.LayoutParams.WRAP_CONTENT + ); params.setScrollFlags(0); mToolbar.setLayoutParams(params); } @@ -66,8 +68,9 @@ public void setToolbarShadowHidden(boolean hidden) { public void setToolbarTranslucent(boolean translucent) { if (mIsTranslucent != translucent) { ViewGroup.LayoutParams params = mScreenView.getLayoutParams(); - ((CoordinatorLayout.LayoutParams) params) - .setBehavior(translucent ? null : new AppBarLayout.ScrollingViewBehavior()); + ((CoordinatorLayout.LayoutParams) params).setBehavior( + translucent ? null : new AppBarLayout.ScrollingViewBehavior() + ); mIsTranslucent = translucent; } } @@ -94,9 +97,9 @@ public Animation onCreateAnimation(int transit, final boolean enter, int nextAni // stack directly from here. // When using the Toolbar back button this is called an extra time with transit = 0 but in // this case we don't want to notify. The way I found to detect is case is check isHidden. - if (transit == 0 - && !isHidden() - && getScreen().getStackAnimation() == Screen.StackAnimation.NONE) { + if ( + transit == 0 && !isHidden() && getScreen().getStackAnimation() == Screen.StackAnimation.NONE + ) { if (enter) { // Android dispatches the animation start event for the fragment that is being added first // however we want the one being dismissed first to match iOS. It also makes more sense @@ -105,13 +108,14 @@ && getScreen().getStackAnimation() == Screen.StackAnimation.NONE) { // the practical way to fix this is delaying dispatching the appear events at the end of // the frame. UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - dispatchOnWillAppear(); - dispatchOnAppear(); - } - }); + new Runnable() { + @Override + public void run() { + dispatchOnWillAppear(); + dispatchOnAppear(); + } + } + ); } else { dispatchOnWillDisappear(); dispatchOnDisappear(); @@ -131,11 +135,15 @@ private void notifyViewAppearTransitionEnd() { @Override public View onCreateView( - LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState + ) { CoordinatorLayout view = new NotifyingCoordinatorLayout(getContext(), this); - CoordinatorLayout.LayoutParams params = - new CoordinatorLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); + CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT + ); params.setBehavior(mIsTranslucent ? null : new AppBarLayout.ScrollingViewBehavior()); mScreenView.setLayoutParams(params); view.addView(recycleView(mScreenView)); @@ -147,8 +155,11 @@ public View onCreateView( // (which is the default) mAppBarLayout.setBackgroundColor(Color.TRANSPARENT); mAppBarLayout.setLayoutParams( - new AppBarLayout.LayoutParams( - AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT)); + new AppBarLayout.LayoutParams( + AppBarLayout.LayoutParams.MATCH_PARENT, + AppBarLayout.LayoutParams.WRAP_CONTENT + ) + ); view.addView(mAppBarLayout); if (mShadowHidden) { @@ -198,21 +209,20 @@ public void dismiss() { private static class NotifyingCoordinatorLayout extends CoordinatorLayout { private final ScreenFragment mFragment; - private final Animation.AnimationListener mAnimationListener = - new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - mFragment.onViewAnimationStart(); - } + private final Animation.AnimationListener mAnimationListener = new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + mFragment.onViewAnimationStart(); + } - @Override - public void onAnimationEnd(Animation animation) { - mFragment.onViewAnimationEnd(); - } + @Override + public void onAnimationEnd(Animation animation) { + mFragment.onViewAnimationEnd(); + } - @Override - public void onAnimationRepeat(Animation animation) {} - }; + @Override + public void onAnimationRepeat(Animation animation) {} + }; public NotifyingCoordinatorLayout(@NonNull Context context, ScreenFragment fragment) { super(context); diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.java b/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.java index eaead31412..49b762ffb5 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.java @@ -47,24 +47,23 @@ public class ScreenStackHeaderConfig extends ViewGroup { private final int mDefaultStartInset; private final int mDefaultStartInsetWithNavigation; - private final OnClickListener mBackClickListener = - new OnClickListener() { - @Override - public void onClick(View view) { - ScreenStackFragment fragment = getScreenFragment(); - if (fragment != null) { - ScreenStack stack = getScreenStack(); - if (stack != null && stack.getRootScreen() == fragment.getScreen()) { - Fragment parentFragment = fragment.getParentFragment(); - if (parentFragment instanceof ScreenStackFragment) { - ((ScreenStackFragment) parentFragment).dismiss(); - } - } else { - fragment.dismiss(); - } + private final OnClickListener mBackClickListener = new OnClickListener() { + @Override + public void onClick(View view) { + ScreenStackFragment fragment = getScreenFragment(); + if (fragment != null) { + ScreenStack stack = getScreenStack(); + if (stack != null && stack.getRootScreen() == fragment.getScreen()) { + Fragment parentFragment = fragment.getParentFragment(); + if (parentFragment instanceof ScreenStackFragment) { + ((ScreenStackFragment) parentFragment).dismiss(); } + } else { + fragment.dismiss(); } - }; + } + } + }; public ScreenStackHeaderConfig(Context context) { super(context); @@ -211,7 +210,8 @@ public void onUpdate() { // hide back button actionBar.setDisplayHomeAsUpEnabled( - getScreenFragment().canNavigateBack() && !mIsBackButtonHidden); + getScreenFragment().canNavigateBack() && !mIsBackButtonHidden + ); // when setSupportActionBar is called a toolbar wrapper gets initialized that overwrites // navigation click listener. The default behavior set in the wrapper is to call into @@ -238,9 +238,13 @@ public void onUpdate() { } if (titleTextView != null) { if (mTitleFontFamily != null || mTitleFontWeight > 0) { - Typeface titleTypeface = - ReactTypefaceUtils.applyStyles( - null, 0, mTitleFontWeight, mTitleFontFamily, getContext().getAssets()); + Typeface titleTypeface = ReactTypefaceUtils.applyStyles( + null, + 0, + mTitleFontWeight, + mTitleFontFamily, + getContext().getAssets() + ); titleTextView.setTypeface(titleTypeface); } if (mTitleFontSize > 0) { @@ -277,14 +281,17 @@ public void onUpdate() { View firstChild = view.getChildAt(0); if (!(firstChild instanceof ImageView)) { throw new JSApplicationIllegalArgumentException( - "Back button header config view should have Image as first child"); + "Back button header config view should have Image as first child" + ); } actionBar.setHomeAsUpIndicator(((ImageView) firstChild).getDrawable()); continue; } - Toolbar.LayoutParams params = - new Toolbar.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + Toolbar.LayoutParams params = new Toolbar.LayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT + ); switch (type) { case LEFT: @@ -421,10 +428,9 @@ public DebugMenuToolbar(Context context) { @Override public boolean showOverflowMenu() { - ((ReactApplication) getContext().getApplicationContext()) - .getReactNativeHost() - .getReactInstanceManager() - .showDevOptionsDialog(); + ((ReactApplication) getContext().getApplicationContext()).getReactNativeHost() + .getReactInstanceManager() + .showDevOptionsDialog(); return true; } } diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.java b/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.java index a5df2d4158..856d5b6adf 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.java @@ -27,7 +27,8 @@ protected ScreenStackHeaderConfig createViewInstance(ThemedReactContext reactCon public void addView(ScreenStackHeaderConfig parent, View child, int index) { if (!(child instanceof ScreenStackHeaderSubview)) { throw new JSApplicationCausedNativeException( - "Config children should be of type " + ScreenStackHeaderSubviewManager.REACT_CLASS); + "Config children should be of type " + ScreenStackHeaderSubviewManager.REACT_CLASS + ); } parent.addConfigSubview((ScreenStackHeaderSubview) child, index); } @@ -130,7 +131,9 @@ public void setTranslucent(ScreenStackHeaderConfig config, boolean translucent) @ReactProp(name = "backButtonInCustomView") public void setBackButtonInCustomView( - ScreenStackHeaderConfig config, boolean backButtonInCustomView) { + ScreenStackHeaderConfig config, + boolean backButtonInCustomView + ) { config.setBackButtonInCustomView(backButtonInCustomView); } @@ -138,7 +141,6 @@ public void setBackButtonInCustomView( public void setDirection(ScreenStackHeaderConfig config, String direction) { config.setDirection(direction); } - // RCT_EXPORT_VIEW_PROPERTY(backTitle, NSString) // RCT_EXPORT_VIEW_PROPERTY(backTitleFontFamily, NSString) // RCT_EXPORT_VIEW_PROPERTY(backTitleFontSize, NSString) diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.java b/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.java index cd69b3dcdc..963d3059c3 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.java @@ -16,8 +16,10 @@ public ScreenStackHeaderSubview(ReactContext context) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY - && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { + if ( + MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && + MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY + ) { // dimensions provided by react mReactWidth = MeasureSpec.getSize(widthMeasureSpec); mReactHeight = MeasureSpec.getSize(heightMeasureSpec); @@ -47,6 +49,6 @@ public enum Type { LEFT, CENTER, RIGHT, - BACK + BACK, } } diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.java b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.java index 57c974bd50..58edf6acd0 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.java @@ -46,14 +46,17 @@ public void setActivityState(Screen view, Integer activityState) { public void setStackPresentation(Screen view, String presentation) { if ("push".equals(presentation)) { view.setStackPresentation(Screen.StackPresentation.PUSH); - } else if ("modal".equals(presentation) - || "containedModal".equals(presentation) - || "fullScreenModal".equals(presentation) - || "formSheet".equals(presentation)) { + } else if ( + "modal".equals(presentation) || + "containedModal".equals(presentation) || + "fullScreenModal".equals(presentation) || + "formSheet".equals(presentation) + ) { // at the moment Android implementation does not handle contained vs regular modals view.setStackPresentation(Screen.StackPresentation.MODAL); - } else if ("transparentModal".equals(presentation) - || "containedTransparentModal".equals((presentation))) { + } else if ( + "transparentModal".equals(presentation) || "containedTransparentModal".equals((presentation)) + ) { // at the moment Android implementation does not handle contained vs regular modals view.setStackPresentation(Screen.StackPresentation.TRANSPARENT_MODAL); } else { @@ -129,17 +132,18 @@ public void setStatusBarHidden(Screen view, Boolean statusBarHidden) { @Override public Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.of( - ScreenDismissedEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onDismissed"), - ScreenWillAppearEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onWillAppear"), - ScreenAppearEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onAppear"), - ScreenWillDisappearEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onWillDisappear"), - ScreenDisappearEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onDisappear"), - StackFinishTransitioningEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onFinishTransitioning")); + ScreenDismissedEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onDismissed"), + ScreenWillAppearEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onWillAppear"), + ScreenAppearEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onAppear"), + ScreenWillDisappearEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onWillDisappear"), + ScreenDisappearEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onDisappear"), + StackFinishTransitioningEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onFinishTransitioning") + ); } } diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.java b/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.java index 771620b403..cc529c2c13 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.java +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.java @@ -17,6 +17,7 @@ import com.facebook.react.bridge.UiThreadUtil; public class ScreenWindowTraits { + // Methods concerning statusBar management were taken from `react-native`'s status bar module: // https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java @@ -45,8 +46,10 @@ protected static void setOrientation(Screen screen, final Activity activity) { return; } - Screen screenForOrientation = - ScreenWindowTraits.findScreenForTrait(screen, Screen.WindowTraits.ORIENTATION); + Screen screenForOrientation = ScreenWindowTraits.findScreenForTrait( + screen, + Screen.WindowTraits.ORIENTATION + ); final Integer orientation; @@ -60,9 +63,9 @@ protected static void setOrientation(Screen screen, final Activity activity) { } protected static void setColor(Screen screen, final Activity activity, ReactContext context) { - if (activity == null - || context == null - || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + if ( + activity == null || context == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP + ) { return; } @@ -70,10 +73,14 @@ protected static void setColor(Screen screen, final Activity activity, ReactCont mDefaultStatusBarColor = activity.getWindow().getStatusBarColor(); } - Screen screenForColor = - ScreenWindowTraits.findScreenForTrait(screen, Screen.WindowTraits.COLOR); - Screen screenForAnimated = - ScreenWindowTraits.findScreenForTrait(screen, Screen.WindowTraits.ANIMATED); + Screen screenForColor = ScreenWindowTraits.findScreenForTrait( + screen, + Screen.WindowTraits.COLOR + ); + Screen screenForAnimated = ScreenWindowTraits.findScreenForTrait( + screen, + Screen.WindowTraits.ANIMATED + ); final Integer color; final boolean animated; @@ -91,32 +98,37 @@ protected static void setColor(Screen screen, final Activity activity, ReactCont } UiThreadUtil.runOnUiThread( - new GuardedRunnable(context) { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public void runGuarded() { - activity - .getWindow() - .addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - int curColor = activity.getWindow().getStatusBarColor(); - ValueAnimator colorAnimation = - ValueAnimator.ofObject(new ArgbEvaluator(), curColor, color); - colorAnimation.addUpdateListener( - new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animator) { - activity.getWindow().setStatusBarColor((Integer) animator.getAnimatedValue()); - } - }); - - if (animated) { - colorAnimation.setDuration(300).setStartDelay(0); - } else { - colorAnimation.setDuration(0).setStartDelay(300); + new GuardedRunnable(context) { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void runGuarded() { + activity + .getWindow() + .addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + int curColor = activity.getWindow().getStatusBarColor(); + ValueAnimator colorAnimation = ValueAnimator.ofObject( + new ArgbEvaluator(), + curColor, + color + ); + colorAnimation.addUpdateListener( + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animator) { + activity.getWindow().setStatusBarColor((Integer) animator.getAnimatedValue()); + } } - colorAnimation.start(); + ); + + if (animated) { + colorAnimation.setDuration(300).setStartDelay(0); + } else { + colorAnimation.setDuration(0).setStartDelay(300); } - }); + colorAnimation.start(); + } + } + ); } protected static void setStyle(Screen screen, final Activity activity, ReactContext context) { @@ -124,8 +136,10 @@ protected static void setStyle(Screen screen, final Activity activity, ReactCont return; } - Screen screenForStyle = - ScreenWindowTraits.findScreenForTrait(screen, Screen.WindowTraits.STYLE); + Screen screenForStyle = ScreenWindowTraits.findScreenForTrait( + screen, + Screen.WindowTraits.STYLE + ); final String style; @@ -137,33 +151,39 @@ protected static void setStyle(Screen screen, final Activity activity, ReactCont if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { UiThreadUtil.runOnUiThread( - new Runnable() { - @TargetApi(Build.VERSION_CODES.M) - @Override - public void run() { - View decorView = activity.getWindow().getDecorView(); - int systemUiVisibilityFlags = decorView.getSystemUiVisibility(); - if ("dark".equals(style)) { - systemUiVisibilityFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - } else { - systemUiVisibilityFlags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - } - decorView.setSystemUiVisibility(systemUiVisibilityFlags); + new Runnable() { + @TargetApi(Build.VERSION_CODES.M) + @Override + public void run() { + View decorView = activity.getWindow().getDecorView(); + int systemUiVisibilityFlags = decorView.getSystemUiVisibility(); + if ("dark".equals(style)) { + systemUiVisibilityFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else { + systemUiVisibilityFlags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } - }); + decorView.setSystemUiVisibility(systemUiVisibilityFlags); + } + } + ); } } protected static void setTranslucent( - Screen screen, final Activity activity, ReactContext context) { + Screen screen, + final Activity activity, + ReactContext context + ) { if (activity == null || context == null) { return; } final boolean translucent; - Screen screenForTranslucent = - ScreenWindowTraits.findScreenForTrait(screen, Screen.WindowTraits.TRANSLUCENT); + Screen screenForTranslucent = ScreenWindowTraits.findScreenForTrait( + screen, + Screen.WindowTraits.TRANSLUCENT + ); if (screenForTranslucent != null && screenForTranslucent.isStatusBarTranslucent() != null) { translucent = screenForTranslucent.isStatusBarTranslucent(); @@ -172,33 +192,36 @@ protected static void setTranslucent( } UiThreadUtil.runOnUiThread( - new GuardedRunnable(context) { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public void runGuarded() { - // If the status bar is translucent hook into the window insets calculations - // and consume all the top insets so no padding will be added under the status bar. - View decorView = activity.getWindow().getDecorView(); - if (translucent) { - decorView.setOnApplyWindowInsetsListener( - new View.OnApplyWindowInsetsListener() { - @Override - public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { - WindowInsets defaultInsets = v.onApplyWindowInsets(insets); - return defaultInsets.replaceSystemWindowInsets( - defaultInsets.getSystemWindowInsetLeft(), - 0, - defaultInsets.getSystemWindowInsetRight(), - defaultInsets.getSystemWindowInsetBottom()); - } - }); - } else { - decorView.setOnApplyWindowInsetsListener(null); - } - - ViewCompat.requestApplyInsets(decorView); + new GuardedRunnable(context) { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void runGuarded() { + // If the status bar is translucent hook into the window insets calculations + // and consume all the top insets so no padding will be added under the status bar. + View decorView = activity.getWindow().getDecorView(); + if (translucent) { + decorView.setOnApplyWindowInsetsListener( + new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { + WindowInsets defaultInsets = v.onApplyWindowInsets(insets); + return defaultInsets.replaceSystemWindowInsets( + defaultInsets.getSystemWindowInsetLeft(), + 0, + defaultInsets.getSystemWindowInsetRight(), + defaultInsets.getSystemWindowInsetBottom() + ); + } + } + ); + } else { + decorView.setOnApplyWindowInsetsListener(null); } - }); + + ViewCompat.requestApplyInsets(decorView); + } + } + ); } protected static void setHidden(Screen screen, final Activity activity) { @@ -208,8 +231,10 @@ protected static void setHidden(Screen screen, final Activity activity) { final boolean hidden; - Screen screenForHidden = - ScreenWindowTraits.findScreenForTrait(screen, Screen.WindowTraits.HIDDEN); + Screen screenForHidden = ScreenWindowTraits.findScreenForTrait( + screen, + Screen.WindowTraits.HIDDEN + ); if (screenForHidden != null && screenForHidden.isStatusBarHidden() != null) { hidden = screenForHidden.isStatusBarHidden(); @@ -218,18 +243,19 @@ protected static void setHidden(Screen screen, final Activity activity) { } UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - if (hidden) { - activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - } else { - activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } + new Runnable() { + @Override + public void run() { + if (hidden) { + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } else { + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } - }); + } + } + ); } protected static void trySetWindowTraits(Screen screen, Activity activity, ReactContext context) { @@ -273,7 +299,9 @@ protected static Screen findScreenForTrait(Screen screen, Screen.WindowTraits tr } protected static @Nullable Screen childScreenWithTraitSet( - Screen screen, Screen.WindowTraits trait) { + Screen screen, + Screen.WindowTraits trait + ) { if (screen == null || screen.getFragment() == null) { return null; } diff --git a/android/src/main/java/com/swmansion/rnscreens/StackFinishTransitioningEvent.java b/android/src/main/java/com/swmansion/rnscreens/StackFinishTransitioningEvent.java index 2e404796cb..6085a1d2f1 100644 --- a/android/src/main/java/com/swmansion/rnscreens/StackFinishTransitioningEvent.java +++ b/android/src/main/java/com/swmansion/rnscreens/StackFinishTransitioningEvent.java @@ -5,6 +5,7 @@ import com.facebook.react.uimanager.events.RCTEventEmitter; public class StackFinishTransitioningEvent extends Event { + public static final String EVENT_NAME = "topFinishTransitioning"; public StackFinishTransitioningEvent(int viewId) {