react-native-navigation 7.42.0 → 7.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/lib/android/app/src/main/java/com/reactnativenavigation/FeatureToggles.kt +62 -0
  2. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java +2 -2
  3. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationApplication.java +13 -3
  4. package/lib/android/app/src/main/java/com/reactnativenavigation/options/ValueAnimationOptions.kt +3 -3
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ColorUtils.java +11 -0
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/StubAnimationListener.kt +19 -0
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +17 -16
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabPresenter.java +0 -1
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsAnimator.kt +2 -2
  10. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +4 -9
  11. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +7 -14
  12. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentPresenter.java +18 -0
  13. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +24 -12
  14. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +52 -24
  15. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +20 -10
  16. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/{TopBarAnimator.kt → TopBarAppearanceAnimator.kt} +4 -2
  17. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarCollapseBehavior.kt +1 -1
  18. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +154 -26
  19. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/statusbar/StatusBarPresenter.kt +212 -0
  20. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +12 -107
  21. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/StatusBarColorAnimator.kt +28 -0
  22. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +34 -2
  23. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewControllerVisibilityInfo.kt +5 -0
  24. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/{BaseViewAnimator.kt → BaseViewAppearanceAnimator.kt} +4 -4
  25. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ColorAnimator.kt +22 -0
  26. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/DefaultViewAnimatorCreator.kt +8 -8
  27. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewAnimatorCreator.kt +2 -2
  28. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewBkgColorProperty.kt +17 -0
  29. package/lib/dist/src/commands/OptionsProcessor.js +8 -1
  30. package/lib/dist/src/interfaces/Options.d.ts +33 -3
  31. package/lib/ios/BottomTabsBasePresenter.m +1 -1
  32. package/lib/ios/RNNConvert.h +0 -1
  33. package/lib/ios/RNNConvert.m +3 -8
  34. package/lib/ios/RNNStackPresenter.m +1 -1
  35. package/lib/src/commands/OptionsProcessor.ts +13 -2
  36. package/lib/src/interfaces/Options.ts +38 -3
  37. package/package.json +1 -1
@@ -0,0 +1,62 @@
1
+ package com.reactnativenavigation
2
+
3
+ import androidx.annotation.VisibleForTesting
4
+
5
+ enum class RNNToggles {
6
+ TOP_BAR_COLOR_ANIMATION__PUSH,
7
+ TOP_BAR_COLOR_ANIMATION__TABS,
8
+ }
9
+
10
+ private val ToggleDefaults = mapOf(
11
+ RNNToggles.TOP_BAR_COLOR_ANIMATION__PUSH to false,
12
+ RNNToggles.TOP_BAR_COLOR_ANIMATION__TABS to false,
13
+ )
14
+
15
+ object RNNFeatureToggles {
16
+ private var init = false
17
+ private var toggles = mutableMapOf<RNNToggles, Boolean>()
18
+
19
+ @JvmStatic
20
+ fun init() {
21
+ assertNotInitialized()
22
+
23
+ init = true
24
+ toggles = ToggleDefaults.toMutableMap()
25
+ }
26
+
27
+ @JvmStatic
28
+ fun init(overrides: Map<RNNToggles, Boolean>) {
29
+ init()
30
+ this.toggles.putAll(overrides)
31
+ }
32
+
33
+ @JvmStatic
34
+ fun init(vararg overrides: Pair<RNNToggles, Boolean>) {
35
+ init(mapOf(*overrides))
36
+ }
37
+
38
+ @JvmStatic
39
+ fun isEnabled(toggleName: RNNToggles): Boolean {
40
+ assertInitialized()
41
+ return toggles.getOrElse(toggleName) { false }
42
+ }
43
+
44
+ @VisibleForTesting
45
+ @JvmStatic
46
+ fun clear() {
47
+ init = false
48
+ toggles.clear()
49
+ }
50
+
51
+ private fun assertNotInitialized() {
52
+ if (init) {
53
+ throw IllegalStateException("FeatureToggles already initialized")
54
+ }
55
+ }
56
+
57
+ private fun assertInitialized() {
58
+ if (!init) {
59
+ throw IllegalStateException("FeatureToggles not initialized")
60
+ }
61
+ }
62
+ }
@@ -3,7 +3,6 @@ package com.reactnativenavigation;
3
3
  import android.annotation.TargetApi;
4
4
  import android.content.Intent;
5
5
  import android.content.res.Configuration;
6
- import android.graphics.Color;
7
6
  import android.os.Build;
8
7
  import android.os.Bundle;
9
8
  import android.view.KeyEvent;
@@ -12,8 +11,8 @@ import android.view.View;
12
11
  import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
13
12
  import com.facebook.react.modules.core.PermissionAwareActivity;
14
13
  import com.facebook.react.modules.core.PermissionListener;
15
- import com.reactnativenavigation.options.Options;
16
14
  import com.reactnativenavigation.viewcontrollers.overlay.OverlayManager;
15
+ import com.reactnativenavigation.viewcontrollers.statusbar.StatusBarPresenter;
17
16
  import com.reactnativenavigation.viewcontrollers.viewcontroller.RootPresenter;
18
17
  import com.reactnativenavigation.react.JsDevReloadHandler;
19
18
  import com.reactnativenavigation.react.ReactGateway;
@@ -51,6 +50,7 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
51
50
  navigator.bindViews();
52
51
  getReactGateway().onActivityCreated(this);
53
52
  setBackPressedCallback();
53
+ StatusBarPresenter.Companion.init(this);
54
54
  }
55
55
 
56
56
  @Override
@@ -9,6 +9,7 @@ import com.facebook.soloader.SoLoader;
9
9
  import com.reactnativenavigation.react.ReactGateway;
10
10
  import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
11
11
 
12
+ import java.util.Collections;
12
13
  import java.io.IOException;
13
14
  import java.util.HashMap;
14
15
  import java.util.Map;
@@ -17,14 +18,23 @@ import androidx.annotation.NonNull;
17
18
 
18
19
  public abstract class NavigationApplication extends Application implements ReactApplication {
19
20
 
20
- private ReactGateway reactGateway;
21
21
  public static NavigationApplication instance;
22
- final Map<String, ExternalComponentCreator> externalComponents = new HashMap<>();
22
+
23
+ private final Map<String, ExternalComponentCreator> externalComponents = new HashMap<>();
24
+ private ReactGateway reactGateway;
25
+
26
+ public NavigationApplication() {
27
+ this(Collections.emptyMap());
28
+ }
29
+
30
+ public NavigationApplication(Map<RNNToggles, Boolean> featureToggleOverrides) {
31
+ instance = this;
32
+ RNNFeatureToggles.init(featureToggleOverrides);
33
+ }
23
34
 
24
35
  @Override
25
36
  public void onCreate() {
26
37
  super.onCreate();
27
- instance = this;
28
38
  try {
29
39
  SoLoader.init(this, OpenSourceMergedSoMapping.INSTANCE);
30
40
  } catch (IOException e) {
@@ -50,9 +50,9 @@ class ValueAnimationOptions {
50
50
  to += this.to[animationValueAccessor!!(view)]
51
51
  }
52
52
  val animator = ObjectAnimator.ofFloat(view,
53
- animProp,
54
- from,
55
- to
53
+ animProp,
54
+ from,
55
+ to
56
56
  )
57
57
  animator.interpolator = interpolator
58
58
  if (duration.hasValue()) animator.duration = duration.get().toLong()
@@ -1,5 +1,7 @@
1
1
  package com.reactnativenavigation.utils;
2
2
 
3
+ import android.graphics.Color;
4
+
3
5
  public class ColorUtils {
4
6
  public static double[] colorToLAB(int color) {
5
7
  final double[] result = new double[3];
@@ -10,4 +12,13 @@ public class ColorUtils {
10
12
  public static int labToColor(double[] lab) {
11
13
  return androidx.core.graphics.ColorUtils.LABToColor(lab[0], lab[1], lab[2]);
12
14
  }
15
+
16
+ public static boolean isColorLight(int color) {
17
+ double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
18
+ return darkness < 0.5;
19
+ }
20
+
21
+ public static int setAlpha(int color, int alpha) {
22
+ return (color & 0x00FFFFFF) | (alpha << 24);
23
+ }
13
24
  }
@@ -0,0 +1,19 @@
1
+ package com.reactnativenavigation.utils
2
+
3
+ import android.animation.Animator
4
+
5
+ open class StubAnimationListener: Animator.AnimatorListener {
6
+ override fun onAnimationStart(animation: Animator) {}
7
+ override fun onAnimationEnd(animation: Animator) {}
8
+ override fun onAnimationCancel(animation: Animator) {}
9
+ override fun onAnimationRepeat(animation: Animator) {}
10
+
11
+ companion object {
12
+ @JvmStatic
13
+ fun onAnimatorEnd(onEnd: (animation: Animator) -> Unit) = object: StubAnimationListener() {
14
+ override fun onAnimationEnd(animation: Animator) {
15
+ onEnd(animation)
16
+ }
17
+ }
18
+ }
19
+ }
@@ -3,7 +3,6 @@ package com.reactnativenavigation.utils
3
3
  import android.app.Activity
4
4
  import android.graphics.Color
5
5
  import android.graphics.Rect
6
- import android.os.Build
7
6
  import android.view.View
8
7
  import android.view.Window
9
8
  import androidx.annotation.ColorInt
@@ -16,7 +15,6 @@ import kotlin.math.ceil
16
15
 
17
16
  object SystemUiUtils {
18
17
  private const val STATUS_BAR_HEIGHT_M = 24
19
- private const val STATUS_BAR_HEIGHT_L = 25
20
18
  internal const val STATUS_BAR_HEIGHT_TRANSLUCENCY = 0.65f
21
19
  private var statusBarHeight = -1
22
20
  var navigationBarDefaultColor = -1
@@ -38,7 +36,7 @@ object SystemUiUtils {
38
36
  val contentViewTop = contentView.top
39
37
  abs(contentViewTop - statusBarHeight)
40
38
  }
41
- } ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) STATUS_BAR_HEIGHT_M else STATUS_BAR_HEIGHT_L
39
+ } ?: STATUS_BAR_HEIGHT_M
42
40
  statusBarHeight
43
41
  }
44
42
  return res
@@ -77,8 +75,6 @@ object SystemUiUtils {
77
75
 
78
76
  @JvmStatic
79
77
  fun setStatusBarColorScheme(window: Window?, view: View, isDark: Boolean) {
80
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return
81
-
82
78
  window?.let {
83
79
  WindowInsetsControllerCompat(window, view).isAppearanceLightStatusBars = isDark
84
80
  // Workaround: on devices with api 30 status bar icons flickers or get hidden when removing view
@@ -121,17 +117,22 @@ object SystemUiUtils {
121
117
  @ColorInt color: Int,
122
118
  translucent: Boolean
123
119
  ) {
124
- val opaqueColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
125
- Color.BLACK
126
- }else{
127
- val colorAlpha = Color.alpha(color)
128
- val alpha = if (translucent && colorAlpha == 255) STATUS_BAR_HEIGHT_TRANSLUCENCY else colorAlpha/255.0f
129
- val red: Int = Color.red(color)
130
- val green: Int = Color.green(color)
131
- val blue: Int = Color.blue(color)
132
- Color.argb(ceil(alpha * 255).toInt(), red, green, blue)
133
- }
134
- window?.statusBarColor = opaqueColor
120
+ val colorAlpha = Color.alpha(color)
121
+ val alpha = if (translucent && colorAlpha == 255) STATUS_BAR_HEIGHT_TRANSLUCENCY else colorAlpha/255.0f
122
+ val red: Int = Color.red(color)
123
+ val green: Int = Color.green(color)
124
+ val blue: Int = Color.blue(color)
125
+ val opaqueColor = Color.argb(ceil(alpha * 255).toInt(), red, green, blue)
126
+ setStatusBarColor(window, opaqueColor)
127
+ }
128
+
129
+ fun setStatusBarColor(window: Window?, color: Int) {
130
+ window?.statusBarColor = color
131
+ }
132
+
133
+ @JvmStatic
134
+ fun getStatusBarColor(window: Window?): Int? {
135
+ return window?.statusBarColor
135
136
  }
136
137
 
137
138
  @JvmStatic
@@ -9,7 +9,6 @@ import android.graphics.drawable.Drawable;
9
9
 
10
10
  import androidx.annotation.NonNull;
11
11
 
12
- import com.aurelhubert.ahbottomnavigation.AHTextView;
13
12
  import com.aurelhubert.ahbottomnavigation.notification.AHNotification;
14
13
  import com.reactnativenavigation.options.BottomTabOptions;
15
14
  import com.reactnativenavigation.options.DotIndicatorOptions;
@@ -1,9 +1,9 @@
1
1
  package com.reactnativenavigation.viewcontrollers.bottomtabs
2
2
 
3
- import com.reactnativenavigation.views.animations.BaseViewAnimator
3
+ import com.reactnativenavigation.views.animations.BaseViewAppearanceAnimator
4
4
  import com.reactnativenavigation.views.bottomtabs.BottomTabs
5
5
 
6
- class BottomTabsAnimator(view: BottomTabs? = null) : BaseViewAnimator<BottomTabs>(HideDirection.Down, view) {
6
+ class BottomTabsAnimator(view: BottomTabs? = null) : BaseViewAppearanceAnimator<BottomTabs>(HideDirection.Down, view) {
7
7
  override fun onShowAnimationEnd() {
8
8
  view.restoreBottomNavigation(false)
9
9
  }
@@ -271,11 +271,11 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
271
271
  private void selectTab(int newIndex, boolean enableSelectionHistory) {
272
272
  saveTabSelection(newIndex, enableSelectionHistory);
273
273
  tabsAttacher.onTabSelected(tabs.get(newIndex));
274
- getCurrentView().setVisibility(View.INVISIBLE);
274
+ getCurrentChild().onDeselected();
275
+
276
+ ViewController<?> previouslyVisible = getCurrentChild();
275
277
  bottomTabs.setCurrentItem(newIndex, false);
276
- getCurrentView().setVisibility(View.VISIBLE);
277
- getCurrentChild().onViewWillAppear();
278
- getCurrentChild().onViewDidAppear();
278
+ getCurrentChild().onSelected(previouslyVisible);
279
279
  }
280
280
 
281
281
  private void saveTabSelection(int newIndex, boolean enableSelectionHistory) {
@@ -287,11 +287,6 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
287
287
  }
288
288
  }
289
289
 
290
- @NonNull
291
- private ViewGroup getCurrentView() {
292
- return tabs.get(bottomTabs.getCurrentItem()).getView();
293
- }
294
-
295
290
  public Animator getPushAnimation(Options appearingOptions) {
296
291
  return presenter.getPushAnimation(appearingOptions);
297
292
  }
@@ -2,30 +2,23 @@ package com.reactnativenavigation.viewcontrollers.child;
2
2
 
3
3
  import android.app.Activity;
4
4
  import android.content.res.Configuration;
5
- import android.os.Build;
6
- import android.util.Log;
7
5
  import android.view.View;
8
6
  import android.view.ViewGroup;
9
- import android.view.WindowInsets;
7
+
8
+ import androidx.annotation.CallSuper;
9
+ import androidx.core.view.ViewCompat;
10
+ import androidx.core.view.WindowInsetsCompat;
10
11
 
11
12
  import com.reactnativenavigation.options.Options;
12
- import com.reactnativenavigation.utils.LogKt;
13
- import com.reactnativenavigation.viewcontrollers.parent.ParentController;
14
- import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
15
- import com.reactnativenavigation.viewcontrollers.viewcontroller.NoOpYellowBoxDelegate;
16
13
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
14
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.NoOpYellowBoxDelegate;
15
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
17
16
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
18
17
  import com.reactnativenavigation.viewcontrollers.viewcontroller.overlay.ViewControllerOverlay;
19
18
  import com.reactnativenavigation.views.component.Component;
20
19
 
21
- import androidx.annotation.CallSuper;
22
- import androidx.core.graphics.Insets;
23
- import androidx.core.view.ViewCompat;
24
- import androidx.core.view.WindowCompat;
25
- import androidx.core.view.WindowInsetsCompat;
26
-
27
20
  public abstract class ChildController<T extends ViewGroup> extends ViewController<T> {
28
- private final Presenter presenter;
21
+ protected final Presenter presenter;
29
22
  private final ChildControllersRegistry childRegistry;
30
23
 
31
24
  public ChildControllersRegistry getChildRegistry() {
@@ -1,6 +1,12 @@
1
1
  package com.reactnativenavigation.viewcontrollers.component;
2
2
 
3
+ import android.animation.Animator;
4
+
5
+ import androidx.annotation.NonNull;
6
+ import androidx.annotation.Nullable;
7
+
3
8
  import com.reactnativenavigation.options.Options;
9
+ import com.reactnativenavigation.viewcontrollers.statusbar.StatusBarPresenter;
4
10
  import com.reactnativenavigation.views.component.ComponentLayout;
5
11
 
6
12
  public class ComponentPresenter extends ComponentPresenterBase {
@@ -35,4 +41,16 @@ public class ComponentPresenter extends ComponentPresenterBase {
35
41
  Options withDefault = options.withDefaultOptions(defaultOptions);
36
42
  setBackgroundColor(view, withDefault);
37
43
  }
44
+
45
+ @Nullable
46
+ public Animator getStatusBarPushAnimation(@NonNull Options appearingOptions) {
47
+ Options appearingOptionsWithDefault = appearingOptions.copy().withDefaultOptions(defaultOptions);
48
+ return StatusBarPresenter.instance.getStatusBarPushAnimation(appearingOptionsWithDefault);
49
+ }
50
+
51
+ @Nullable
52
+ public Animator getStatusBarPopAnimation(@NonNull Options appearingOptions, @NonNull Options disappearingOptions) {
53
+ Options appearingOptionsWithDefault = appearingOptions.copy().withDefaultOptions(defaultOptions);
54
+ return StatusBarPresenter.instance.getStatusBarPopAnimation(appearingOptionsWithDefault, disappearingOptions);
55
+ }
38
56
  }
@@ -1,26 +1,26 @@
1
1
  package com.reactnativenavigation.viewcontrollers.component;
2
2
 
3
+ import static com.reactnativenavigation.utils.ObjectUtils.perform;
4
+
5
+ import android.animation.Animator;
3
6
  import android.app.Activity;
4
7
  import android.content.res.Configuration;
5
8
  import android.view.View;
6
9
 
7
- import com.reactnativenavigation.utils.LogKt;
8
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
9
- import com.reactnativenavigation.options.Options;
10
- import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
11
- import com.reactnativenavigation.utils.SystemUiUtils;
12
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ReactViewCreator;
13
- import com.reactnativenavigation.viewcontrollers.child.ChildController;
14
- import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
15
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
16
- import com.reactnativenavigation.views.component.ComponentLayout;
17
-
18
10
  import androidx.annotation.NonNull;
11
+ import androidx.annotation.Nullable;
19
12
  import androidx.core.graphics.Insets;
20
13
  import androidx.core.view.ViewCompat;
21
14
  import androidx.core.view.WindowInsetsCompat;
22
15
 
23
- import static com.reactnativenavigation.utils.ObjectUtils.perform;
16
+ import com.reactnativenavigation.options.Options;
17
+ import com.reactnativenavigation.utils.SystemUiUtils;
18
+ import com.reactnativenavigation.viewcontrollers.child.ChildController;
19
+ import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
20
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
21
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ReactViewCreator;
22
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
23
+ import com.reactnativenavigation.views.component.ComponentLayout;
24
24
 
25
25
  public class ComponentViewController extends ChildController<ComponentLayout> {
26
26
  private final String componentName;
@@ -64,6 +64,18 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
64
64
  presenter.setDefaultOptions(defaultOptions);
65
65
  }
66
66
 
67
+ @Nullable
68
+ @Override
69
+ public Animator getPushAnimations(Options appearingOptions) {
70
+ return this.presenter.getStatusBarPushAnimation(appearingOptions);
71
+ }
72
+
73
+ @Nullable
74
+ @Override
75
+ public Animator getPopAnimations(Options appearingOptions, Options disappearingOptions) {
76
+ return this.presenter.getStatusBarPopAnimation(appearingOptions, disappearingOptions);
77
+ }
78
+
67
79
  @Override
68
80
  public ScrollEventListener getScrollEventListener() {
69
81
  return perform(view, null, ComponentLayout::getScrollEventListener);
@@ -1,10 +1,23 @@
1
1
  package com.reactnativenavigation.viewcontrollers.stack;
2
2
 
3
+ import static com.reactnativenavigation.react.Constants.HARDWARE_BACK_BUTTON_ID;
4
+ import static com.reactnativenavigation.utils.CollectionUtils.requireLast;
5
+ import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.matchParentWithBehaviour;
6
+ import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.updateBottomMargin;
7
+ import static com.reactnativenavigation.utils.ObjectUtils.perform;
8
+
3
9
  import android.app.Activity;
4
10
  import android.content.res.Configuration;
5
11
  import android.view.View;
6
12
  import android.view.ViewGroup;
7
13
 
14
+ import androidx.annotation.NonNull;
15
+ import androidx.annotation.RestrictTo;
16
+ import androidx.annotation.Size;
17
+ import androidx.annotation.VisibleForTesting;
18
+ import androidx.coordinatorlayout.widget.CoordinatorLayout;
19
+ import androidx.viewpager.widget.ViewPager;
20
+
8
21
  import com.facebook.react.ReactRootView;
9
22
  import com.reactnativenavigation.options.ButtonOptions;
10
23
  import com.reactnativenavigation.options.Options;
@@ -18,7 +31,9 @@ import com.reactnativenavigation.viewcontrollers.parent.ParentController;
18
31
  import com.reactnativenavigation.viewcontrollers.stack.topbar.TopBarController;
19
32
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.BackButtonHelper;
20
33
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
34
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.TopBarVisibilityInfo;
21
35
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
36
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewControllerVisibilityInfo;
22
37
  import com.reactnativenavigation.views.component.Component;
23
38
  import com.reactnativenavigation.views.stack.StackBehaviour;
24
39
  import com.reactnativenavigation.views.stack.StackLayout;
@@ -31,19 +46,6 @@ import java.util.Collection;
31
46
  import java.util.Iterator;
32
47
  import java.util.List;
33
48
 
34
- import androidx.annotation.NonNull;
35
- import androidx.annotation.RestrictTo;
36
- import androidx.annotation.Size;
37
- import androidx.annotation.VisibleForTesting;
38
- import androidx.coordinatorlayout.widget.CoordinatorLayout;
39
- import androidx.viewpager.widget.ViewPager;
40
-
41
- import static com.reactnativenavigation.react.Constants.HARDWARE_BACK_BUTTON_ID;
42
- import static com.reactnativenavigation.utils.CollectionUtils.*;
43
- import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.matchParentWithBehaviour;
44
- import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.updateBottomMargin;
45
- import static com.reactnativenavigation.utils.ObjectUtils.perform;
46
-
47
49
  public class StackController extends ParentController<StackLayout> {
48
50
 
49
51
  private IdStack<ViewController<?>> stack = new IdStack<>();
@@ -95,6 +97,19 @@ public class StackController extends ParentController<StackLayout> {
95
97
  return stack.peek();
96
98
  }
97
99
 
100
+ @Override
101
+ public void onSelected(ViewController<?> previousVC) {
102
+ presenter.bindNewViewController(previousVC, this);
103
+ super.onSelected(previousVC);
104
+ }
105
+
106
+ @NonNull
107
+ @Override
108
+ public ViewControllerVisibilityInfo getVisibilityInfo() {
109
+ TopBarVisibilityInfo topBarInfo = topBarController.getVisibilityInfo();
110
+ return new ViewControllerVisibilityInfo(topBarInfo);
111
+ }
112
+
98
113
  @Override
99
114
  public void onAttachToParent() {
100
115
  if (!isEmpty() && !getCurrentChild().isDestroyed() && !isViewShown()) {
@@ -159,16 +174,19 @@ public class StackController extends ParentController<StackLayout> {
159
174
  listener.onError("A stack can't contain two children with the same id: " + child.getId());
160
175
  return;
161
176
  }
162
- final ViewController<?> toRemove = stack.peek();
163
- if (size() > 0) backButtonHelper.addToPushedChild(child);
164
- child.setParentController(this);
165
- stack.push(child.getId(), child);
166
- if (!isViewCreated()) return;
177
+
178
+ final ViewController<?> toRemove = pushChildToStack(child);
179
+
180
+ if (!isViewCreated()) {
181
+ return;
182
+ }
183
+
167
184
  Options resolvedOptions = resolveCurrentOptions(presenter.getDefaultOptions());
168
- addChildToStack(child, resolvedOptions);
185
+ updateChildLayout(child, resolvedOptions);
186
+
169
187
  if (toRemove != null) {
170
- StackAnimationOptions animation = resolvedOptions.animations.push;
171
- if (animation.enabled.isTrueOrUndefined()) {
188
+ StackAnimationOptions animOptions = resolvedOptions.animations.push;
189
+ if (animOptions.enabled.isTrueOrUndefined()) {
172
190
  animator.push(
173
191
  child,
174
192
  toRemove,
@@ -195,7 +213,17 @@ public class StackController extends ParentController<StackLayout> {
195
213
  listener.onSuccess(toAdd.getId());
196
214
  }
197
215
 
198
- private void addChildToStack(ViewController<?> child, Options resolvedOptions) {
216
+ private ViewController<?> pushChildToStack(ViewController<?> child) {
217
+ final ViewController<?> toRemove = stack.peek();
218
+
219
+ if (size() > 0) backButtonHelper.addToPushedChild(child);
220
+
221
+ child.setParentController(this);
222
+ stack.push(child.getId(), child);
223
+ return toRemove;
224
+ }
225
+
226
+ private void updateChildLayout(ViewController<?> child, Options resolvedOptions) {
199
227
  child.setWaitForRender(resolvedOptions.animations.push.waitForRender);
200
228
  if (size() == 1) presenter.applyInitialChildLayoutOptions(resolvedOptions);
201
229
  getView().addView(child.getView(), getView().getChildCount() - 1, matchParentWithBehaviour(new StackBehaviour(this)));
@@ -222,7 +250,7 @@ public class StackController extends ParentController<StackLayout> {
222
250
  child.setParentController(this);
223
251
  stack.push(child.getId(), child);
224
252
  Options resolvedOptions = resolveCurrentOptions(presenter.getDefaultOptions());
225
- addChildToStack(child, resolvedOptions);
253
+ updateChildLayout(child, resolvedOptions);
226
254
 
227
255
  CommandListener listenerAdapter = new CommandListenerAdapter() {
228
256
  @Override
@@ -316,7 +344,7 @@ public class StackController extends ParentController<StackLayout> {
316
344
  appearing,
317
345
  disappearing,
318
346
  disappearingOptions,
319
- presenter.getAdditionalPopAnimations(appearingOptions, disappearingOptions),
347
+ presenter.getAdditionalPopAnimations(appearingOptions, disappearingOptions, appearing),
320
348
  () -> finishPopping(appearing, disappearing, listener)
321
349
  );
322
350
  } else {
@@ -37,6 +37,7 @@ import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonContr
37
37
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonPresenter;
38
38
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.IconResolver;
39
39
  import com.reactnativenavigation.viewcontrollers.stack.topbar.title.TitleBarReactViewController;
40
+ import com.reactnativenavigation.viewcontrollers.statusbar.StatusBarPresenter;
40
41
  import com.reactnativenavigation.viewcontrollers.viewcontroller.IReactView;
41
42
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
42
43
  import com.reactnativenavigation.views.stack.topbar.TopBar;
@@ -191,6 +192,12 @@ public class StackPresenter {
191
192
  componentLeftButtons.remove(child.getView());
192
193
  }
193
194
 
195
+ public void bindNewViewController(ViewController<?> previousVC, ViewController<?> newVC) {
196
+ Options options = newVC.resolveCurrentOptions(defaultOptions);
197
+ topBarController.bindNewViewController(previousVC, newVC);
198
+ StatusBarPresenter.instance.bindViewController(options.statusBar);
199
+ }
200
+
194
201
  private void destroyButtons(@Nullable Map<String, ButtonController> buttons) {
195
202
  if (buttons != null)
196
203
  forEach(buttons.values(), ViewController::destroy);
@@ -233,7 +240,7 @@ public class StackPresenter {
233
240
 
234
241
  topBar.setBorderHeight(topBarOptions.borderHeight.get(0d));
235
242
  topBar.setBorderColor(topBarOptions.borderColor.get(DEFAULT_BORDER_COLOR));
236
- topBar.setBackgroundColor(topBarOptions.background.color.get(Color.WHITE));
243
+ topBarController.setBackgroundColor(topBarOptions, Color.WHITE);
237
244
 
238
245
  if (topBarOptions.background.component.hasValue()) {
239
246
  View createdComponent = findBackgroundComponent(topBarOptions.background.component);
@@ -417,18 +424,23 @@ public class StackPresenter {
417
424
  }
418
425
  }
419
426
 
420
- public List<Animator> getAdditionalPushAnimations(StackController stack, ViewController<?> appearing,
427
+ public List<Animator> getAdditionalPushAnimations(
428
+ StackController stack,
429
+ ViewController<?> appearingCtrl,
421
430
  Options appearingOptions) {
422
431
  return CollectionUtils.asList(
423
- topBarController.getPushAnimation(appearingOptions,
424
- getTopBarTranslationAnimationDelta(stack, appearing)),
425
- perform(bottomTabsController, null, btc -> btc.getPushAnimation(appearingOptions)));
432
+ topBarController.getPushAnimation(appearingOptions, getTopBarTranslationAnimationDelta(stack, appearingCtrl)),
433
+ perform(appearingCtrl, null, vc -> vc.getPushAnimations(appearingOptions)),
434
+ perform(bottomTabsController, null, btc -> btc.getPushAnimation(appearingOptions)
435
+ ));
426
436
  }
427
437
 
428
- public List<Animator> getAdditionalPopAnimations(Options appearingOptions, Options disappearingOptions) {
438
+ public List<Animator> getAdditionalPopAnimations(Options appearingOptions, Options disappearingOptions, ViewController<?> appearingCtrl) {
429
439
  return CollectionUtils.asList(
430
440
  topBarController.getPopAnimation(appearingOptions, disappearingOptions),
431
- perform(bottomTabsController, null, btc -> btc.getPopAnimation(appearingOptions, disappearingOptions)));
441
+ perform(appearingCtrl, null, vc -> vc.getPopAnimations(appearingOptions, disappearingOptions)),
442
+ perform(bottomTabsController, null, btc -> btc.getPopAnimation(appearingOptions, disappearingOptions)
443
+ ));
432
444
  }
433
445
 
434
446
  public List<Animator> getAdditionalSetRootAnimations(StackController stack, ViewController<?> appearing,
@@ -618,9 +630,7 @@ public class StackPresenter {
618
630
  if (resolveOptions.subtitle.font.hasValue()) {
619
631
  topBar.setSubtitleTypeface(typefaceLoader, resolveOptions.subtitle.font);
620
632
  }
621
-
622
- if (topBarOptions.background.color.hasValue())
623
- topBar.setBackgroundColor(topBarOptions.background.color.get());
633
+ topBarController.setBackgroundColor(topBarOptions);
624
634
 
625
635
  if (topBarOptions.background.component.hasValue()) {
626
636
  if (backgroundControllers.containsKey(component)) {
@@ -1,9 +1,11 @@
1
1
  package com.reactnativenavigation.viewcontrollers.stack.topbar
2
2
 
3
- import com.reactnativenavigation.views.animations.BaseViewAnimator
3
+ import com.reactnativenavigation.views.animations.BaseViewAppearanceAnimator
4
4
  import com.reactnativenavigation.views.stack.topbar.TopBar
5
5
 
6
- class TopBarAnimator @JvmOverloads constructor(view: TopBar? = null) : BaseViewAnimator<TopBar>(HideDirection.Up, view) {
6
+ class TopBarAppearanceAnimator @JvmOverloads constructor(view: TopBar? = null)
7
+ : BaseViewAppearanceAnimator<TopBar>(HideDirection.Up, view) {
8
+
7
9
  @Suppress("UNUSED_PARAMETER")
8
10
  fun hideOnScroll(translationStart: Float, translationEndDy: Float) {
9
11
  // NOOP for now - this entire mechanism needs to be reimplemented as it relies on bridge events which are obsolete in TurboModules config
@@ -7,7 +7,7 @@ import com.reactnativenavigation.views.stack.topbar.TopBar
7
7
 
8
8
  class TopBarCollapseBehavior(private val topBar: TopBar) : ScrollEventListener.OnScrollListener, ScrollEventListener.OnDragListener {
9
9
  private var scrollEventListener: ScrollEventListener? = null
10
- private val animator: TopBarAnimator = TopBarAnimator(topBar)
10
+ private val animator: TopBarAppearanceAnimator = TopBarAppearanceAnimator(topBar)
11
11
 
12
12
  fun enableCollapse(scrollEventListener: ScrollEventListener?) {
13
13
  this.scrollEventListener = scrollEventListener