react-native-navigation 7.23.1-snapshot.421 → 7.23.1-snapshot.434

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 (25) hide show
  1. package/lib/android/app/build.gradle +3 -3
  2. package/lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java +5 -2
  3. package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalFrameLayout.kt +3 -3
  4. package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalViewManager.kt +11 -8
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +168 -0
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +12 -16
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +18 -11
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java +2 -2
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +33 -18
  10. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +52 -71
  11. package/lib/android/app/src/main/java/com/reactnativenavigation/views/component/ComponentLayout.java +2 -0
  12. package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/ReactImageMatrixAnimator.kt +2 -3
  13. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/TopBar.java +1 -2
  14. package/lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java +7 -6
  15. package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/PresenterTest.java +25 -10
  16. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.java +6 -3
  17. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java +2 -1
  18. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewControllerTest.java +4 -4
  19. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/parent/ParentControllerTest.java +4 -0
  20. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/sidemenu/SideMenuControllerTest.java +6 -2
  21. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.kt +2 -2
  22. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenterTest.kt +3 -3
  23. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewControllerTest.java +4 -1
  24. package/package.json +2 -2
  25. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/StatusBarUtils.kt +0 -39
@@ -172,13 +172,13 @@ allprojects { p ->
172
172
  }
173
173
 
174
174
  dependencies {
175
- implementation "androidx.core:core-ktx:1.3.2"
175
+ implementation "androidx.core:core-ktx:1.6.0"
176
176
  implementation "org.jetbrains.kotlin:$kotlinStdlib:$kotlinVersion"
177
177
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesCore"
178
178
  implementation "androidx.constraintlayout:constraintlayout:2.0.4"
179
179
 
180
- implementation 'androidx.appcompat:appcompat:1.1.0'
181
- implementation 'androidx.annotation:annotation:1.1.0'
180
+ implementation 'androidx.appcompat:appcompat:1.3.1'
181
+ implementation 'androidx.annotation:annotation:1.2.0'
182
182
  implementation 'com.google.android.material:material:1.2.0-alpha03'
183
183
 
184
184
  implementation 'com.github.wix-playground:ahbottomnavigation:3.3.0'
@@ -23,7 +23,7 @@ import com.reactnativenavigation.options.parsers.TypefaceLoader;
23
23
  import com.reactnativenavigation.react.events.EventEmitter;
24
24
  import com.reactnativenavigation.utils.LaunchArgsParser;
25
25
  import com.reactnativenavigation.utils.Now;
26
- import com.reactnativenavigation.utils.StatusBarUtils;
26
+ import com.reactnativenavigation.utils.SystemUiUtils;
27
27
  import com.reactnativenavigation.utils.UiThread;
28
28
  import com.reactnativenavigation.utils.UiUtils;
29
29
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
@@ -34,6 +34,8 @@ import java.util.Objects;
34
34
 
35
35
  import static com.reactnativenavigation.utils.UiUtils.pxToDp;
36
36
 
37
+ import android.app.Activity;
38
+
37
39
  public class NavigationModule extends ReactContextBaseJavaModule {
38
40
  private static final String NAME = "RNNBridgeModule";
39
41
 
@@ -88,10 +90,11 @@ public class NavigationModule extends ReactContextBaseJavaModule {
88
90
 
89
91
  private WritableMap createNavigationConstantsMap() {
90
92
  ReactApplicationContext ctx = getReactApplicationContext();
93
+ final Activity currentActivity = ctx.getCurrentActivity();
91
94
  WritableMap constants = Arguments.createMap();
92
95
  constants.putString(Constants.BACK_BUTTON_JS_KEY, Constants.BACK_BUTTON_ID);
93
96
  constants.putDouble(Constants.BOTTOM_TABS_HEIGHT_KEY, pxToDp(ctx, UiUtils.getBottomTabsHeight(ctx)));
94
- constants.putDouble(Constants.STATUS_BAR_HEIGHT_KEY, pxToDp(ctx, StatusBarUtils.getStatusBarHeight(ctx)));
97
+ constants.putDouble(Constants.STATUS_BAR_HEIGHT_KEY, pxToDp(ctx, SystemUiUtils.getStatusBarHeight(currentActivity)));
95
98
  constants.putDouble(Constants.TOP_BAR_HEIGHT_KEY, pxToDp(ctx, UiUtils.getTopBarHeight(ctx)));
96
99
  return constants;
97
100
  }
@@ -2,7 +2,7 @@ package com.reactnativenavigation.react.modal
2
2
 
3
3
  import android.widget.FrameLayout
4
4
  import com.facebook.react.bridge.ReactContext
5
- import com.reactnativenavigation.utils.StatusBarUtils
5
+ import com.reactnativenavigation.utils.SystemUiUtils
6
6
 
7
7
  class ModalFrameLayout(context: ReactContext) : FrameLayout(context) {
8
8
  val modalContentLayout = ModalContentLayout(context)
@@ -11,9 +11,9 @@ class ModalFrameLayout(context: ReactContext) : FrameLayout(context) {
11
11
  addView(modalContentLayout, MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT)
12
12
  .apply {
13
13
  val translucent = context.currentActivity?.window?.let {
14
- StatusBarUtils.isTranslucent(it)
14
+ SystemUiUtils.isTranslucent(it)
15
15
  } ?: false
16
- topMargin = if (translucent) 0 else StatusBarUtils.getStatusBarHeight(context)
16
+ topMargin = if (translucent) 0 else SystemUiUtils.getStatusBarHeight(context.currentActivity)
17
17
  })
18
18
  }
19
19
  }
@@ -1,5 +1,6 @@
1
1
  package com.reactnativenavigation.react.modal
2
2
 
3
+ import android.app.Activity
3
4
  import android.content.Context
4
5
  import android.graphics.Point
5
6
  import android.view.WindowManager
@@ -21,7 +22,7 @@ import com.reactnativenavigation.options.parseTransitionAnimationOptions
21
22
  import com.reactnativenavigation.options.parsers.JSONParser
22
23
  import com.reactnativenavigation.react.CommandListener
23
24
  import com.reactnativenavigation.react.CommandListenerAdapter
24
- import com.reactnativenavigation.utils.StatusBarUtils
25
+ import com.reactnativenavigation.utils.SystemUiUtils
25
26
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator
26
27
 
27
28
  private const val MODAL_MANAGER_NAME = "RNNModalViewManager"
@@ -107,18 +108,18 @@ class ModalViewManager(val reactContext: ReactContext) : ViewGroupManager<ModalH
107
108
  }
108
109
  }
109
110
 
110
- private fun getModalHostSize(context: Context): Point {
111
+ private fun getModalHostSize(activity: Activity): Point {
111
112
  val MIN_POINT = Point()
112
113
  val MAX_POINT = Point()
113
114
  val SIZE_POINT = Point()
114
- val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
115
+ val wm = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
115
116
  val display = Assertions.assertNotNull(wm).defaultDisplay
116
117
  // getCurrentSizeRange will return the min and max width and height that the window can be
117
118
  display.getCurrentSizeRange(MIN_POINT, MAX_POINT)
118
119
  // getSize will return the dimensions of the screen in its current orientation
119
120
  display.getSize(SIZE_POINT)
120
121
  val attrs = intArrayOf(android.R.attr.windowFullscreen)
121
- val theme = context.theme
122
+ val theme = activity.theme
122
123
  val ta = theme.obtainStyledAttributes(attrs)
123
124
  val windowFullscreen = ta.getBoolean(0, false)
124
125
 
@@ -126,7 +127,7 @@ private fun getModalHostSize(context: Context): Point {
126
127
  // because Display.getCurrentSizeRange doesn't include it.
127
128
  var statusBarHeight = 0
128
129
  if (windowFullscreen) {
129
- statusBarHeight = StatusBarUtils.getStatusBarHeight(context)
130
+ statusBarHeight = SystemUiUtils.getStatusBarHeight(activity)
130
131
  }
131
132
  return if (SIZE_POINT.x < SIZE_POINT.y) {
132
133
  // If we are vertical the width value comes from min width and height comes from max height
@@ -140,8 +141,10 @@ private fun getModalHostSize(context: Context): Point {
140
141
  private class ModalHostShadowNode : LayoutShadowNode() {
141
142
  override fun addChildAt(child: ReactShadowNodeImpl, i: Int) {
142
143
  super.addChildAt(child, i)
143
- val modalSize = getModalHostSize(themedContext)
144
- child.setStyleWidth(modalSize.x.toFloat())
145
- child.setStyleHeight(modalSize.y.toFloat())
144
+ themedContext?.currentActivity?.let {
145
+ val modalSize = getModalHostSize(it)
146
+ child.setStyleWidth(modalSize.x.toFloat())
147
+ child.setStyleHeight(modalSize.y.toFloat())
148
+ }
146
149
  }
147
150
  }
@@ -0,0 +1,168 @@
1
+ package com.reactnativenavigation.utils
2
+
3
+ import android.app.Activity
4
+ import android.graphics.Color
5
+ import android.graphics.Rect
6
+ import android.os.Build
7
+ import android.view.View
8
+ import android.view.Window
9
+ import androidx.annotation.ColorInt
10
+ import androidx.core.view.WindowCompat
11
+ import androidx.core.view.WindowInsetsCompat
12
+ import androidx.core.view.WindowInsetsControllerCompat
13
+ import kotlin.math.abs
14
+ import kotlin.math.ceil
15
+
16
+
17
+ object SystemUiUtils {
18
+ private const val STATUS_BAR_HEIGHT_M = 24
19
+ private const val STATUS_BAR_HEIGHT_L = 25
20
+ private const val STATUS_BAR_HEIGHT_TRANSLUCENCY = 0.65f
21
+ private var statusBarHeight = -1
22
+ var navigationBarDefaultColor = -1
23
+ private set
24
+
25
+
26
+ @JvmStatic
27
+ fun getStatusBarHeight(activity: Activity?): Int {
28
+ val res = if (statusBarHeight > 0) {
29
+ statusBarHeight
30
+ } else {
31
+ statusBarHeight = activity?.let {
32
+ val rectangle = Rect()
33
+ val window: Window = activity.window
34
+ window.decorView.getWindowVisibleDisplayFrame(rectangle)
35
+ val statusBarHeight: Int = rectangle.top
36
+ val contentView = window.findViewById<View>(Window.ID_ANDROID_CONTENT)
37
+ contentView?.let {
38
+ val contentViewTop = contentView.top
39
+ abs(contentViewTop - statusBarHeight)
40
+ }
41
+ } ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) STATUS_BAR_HEIGHT_M else STATUS_BAR_HEIGHT_L
42
+ statusBarHeight
43
+ }
44
+ return res
45
+ }
46
+
47
+ @JvmStatic
48
+ fun saveStatusBarHeight(height: Int) {
49
+ statusBarHeight = height
50
+ }
51
+
52
+
53
+ @JvmStatic
54
+ fun getStatusBarHeightDp(activity: Activity?): Int {
55
+ return UiUtils.pxToDp(activity, getStatusBarHeight(activity).toFloat())
56
+ .toInt()
57
+ }
58
+
59
+ @JvmStatic
60
+ fun hideNavigationBar(window: Window?, view: View) {
61
+ window?.let {
62
+ WindowCompat.setDecorFitsSystemWindows(window, false)
63
+ WindowInsetsControllerCompat(window, view).let { controller ->
64
+ controller.hide(WindowInsetsCompat.Type.navigationBars())
65
+ controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
66
+ }
67
+ }
68
+ }
69
+
70
+ @JvmStatic
71
+ fun showNavigationBar(window: Window?, view: View) {
72
+ window?.let {
73
+ WindowCompat.setDecorFitsSystemWindows(window, true)
74
+ WindowInsetsControllerCompat(window, view).show(WindowInsetsCompat.Type.navigationBars())
75
+ }
76
+ }
77
+
78
+ @JvmStatic
79
+ fun setStatusBarColorScheme(window: Window?, view: View, isDark: Boolean) {
80
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return
81
+
82
+ window?.let {
83
+ WindowInsetsControllerCompat(window, view).isAppearanceLightStatusBars = isDark
84
+ // Workaround: on devices with api 30 status bar icons flickers or get hidden when removing view
85
+ //turns out it is a bug on such devices, fixed by using system flags until it is fixed.
86
+ var flags = view.systemUiVisibility
87
+ flags = if (isDark) {
88
+ flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
89
+ } else {
90
+ flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
91
+ }
92
+
93
+ view.systemUiVisibility = flags
94
+ }
95
+ }
96
+
97
+ @JvmStatic
98
+ fun setStatusBarTranslucent(window: Window?) {
99
+ window?.let {
100
+ setStatusBarColor(window, window.statusBarColor, true)
101
+ }
102
+ }
103
+
104
+ @JvmStatic
105
+ fun isTranslucent(window: Window?): Boolean {
106
+ return window?.let {
107
+ Color.alpha(it.statusBarColor) < 255
108
+ } ?: false
109
+ }
110
+
111
+ @JvmStatic
112
+ fun clearStatusBarTranslucency(window: Window?) {
113
+ window?.let {
114
+ setStatusBarColor(it, it.statusBarColor, false)
115
+ }
116
+ }
117
+
118
+ @JvmStatic
119
+ fun setStatusBarColor(
120
+ window: Window?,
121
+ @ColorInt color: Int,
122
+ translucent: Boolean
123
+ ) {
124
+ val opaqueColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
125
+ Color.BLACK
126
+ }else{
127
+ val alpha = if (translucent) STATUS_BAR_HEIGHT_TRANSLUCENCY else 1f
128
+ val red: Int = Color.red(color)
129
+ val green: Int = Color.green(color)
130
+ val blue: Int = Color.blue(color)
131
+ Color.argb(ceil(alpha * 255).toInt(), red, green, blue)
132
+ }
133
+ window?.statusBarColor = opaqueColor
134
+ }
135
+
136
+ @JvmStatic
137
+ fun hideStatusBar(window: Window?, view: View) {
138
+ window?.let {
139
+ WindowCompat.setDecorFitsSystemWindows(window, false)
140
+ WindowInsetsControllerCompat(window, view).let { controller ->
141
+ controller.hide(WindowInsetsCompat.Type.statusBars())
142
+ controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
143
+ }
144
+ }
145
+ }
146
+
147
+ @JvmStatic
148
+ fun showStatusBar(window: Window?, view: View) {
149
+ window?.let {
150
+ WindowCompat.setDecorFitsSystemWindows(window, true)
151
+ WindowInsetsControllerCompat(window, view).show(WindowInsetsCompat.Type.statusBars())
152
+ }
153
+ }
154
+
155
+ @JvmStatic
156
+ fun setNavigationBarBackgroundColor(window: Window?, color: Int, lightColor: Boolean) {
157
+ window?.let {
158
+ if (navigationBarDefaultColor == -1) {
159
+ navigationBarDefaultColor = window.navigationBarColor
160
+ }
161
+ WindowInsetsControllerCompat(window, window.decorView).let { controller ->
162
+ controller.isAppearanceLightNavigationBars = lightColor
163
+ }
164
+ window.navigationBarColor = color
165
+ }
166
+ }
167
+
168
+ }
@@ -2,12 +2,16 @@ 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;
5
7
  import android.view.View;
6
8
  import android.view.ViewGroup;
9
+ import android.view.WindowInsets;
7
10
 
8
11
  import com.reactnativenavigation.options.Options;
12
+ import com.reactnativenavigation.utils.LogKt;
13
+ import com.reactnativenavigation.viewcontrollers.parent.ParentController;
9
14
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
10
- import com.reactnativenavigation.utils.StatusBarUtils;
11
15
  import com.reactnativenavigation.viewcontrollers.viewcontroller.NoOpYellowBoxDelegate;
12
16
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
13
17
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
@@ -15,7 +19,9 @@ import com.reactnativenavigation.viewcontrollers.viewcontroller.overlay.ViewCont
15
19
  import com.reactnativenavigation.views.component.Component;
16
20
 
17
21
  import androidx.annotation.CallSuper;
22
+ import androidx.core.graphics.Insets;
18
23
  import androidx.core.view.ViewCompat;
24
+ import androidx.core.view.WindowCompat;
19
25
  import androidx.core.view.WindowInsetsCompat;
20
26
 
21
27
  public abstract class ChildController<T extends ViewGroup> extends ViewController<T> {
@@ -61,7 +67,7 @@ public abstract class ChildController<T extends ViewGroup> extends ViewControlle
61
67
  }
62
68
 
63
69
  public void onViewBroughtToFront() {
64
- presenter.onViewBroughtToFront(resolveCurrentOptions());
70
+ presenter.onViewBroughtToFront(this, resolveCurrentOptions());
65
71
  }
66
72
 
67
73
  @Override
@@ -73,7 +79,7 @@ public abstract class ChildController<T extends ViewGroup> extends ViewControlle
73
79
  @Override
74
80
  public void mergeOptions(Options options) {
75
81
  if (options == Options.EMPTY) return;
76
- if (isViewShown()) presenter.mergeOptions(getView(), options);
82
+ if (isViewShown()) presenter.mergeOptions(this, options);
77
83
  super.mergeOptions(options);
78
84
  performOnParentController(parentController -> parentController.mergeChildOptions(options, this));
79
85
  }
@@ -93,23 +99,13 @@ public abstract class ChildController<T extends ViewGroup> extends ViewControlle
93
99
  getView().getParent() != null;
94
100
  }
95
101
 
96
- private WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
97
- StatusBarUtils.saveStatusBarHeight(insets.getSystemWindowInsetTop());
98
- return applyWindowInsets(findController(view), insets);
99
- }
100
-
101
- protected WindowInsetsCompat applyWindowInsets(ViewController<?> view, WindowInsetsCompat insets) {
102
- return insets.replaceSystemWindowInsets(
103
- insets.getSystemWindowInsetLeft(),
104
- 0,
105
- insets.getSystemWindowInsetRight(),
106
- insets.getSystemWindowInsetBottom()
107
- );
102
+ protected WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
103
+ return insets;
108
104
  }
109
105
 
110
106
  @Override
111
107
  public void onConfigurationChanged(Configuration newConfig) {
112
108
  super.onConfigurationChanged(newConfig);
113
- presenter.onConfigurationChanged(this,options);
109
+ presenter.onConfigurationChanged(this, options);
114
110
  }
115
111
  }
@@ -4,10 +4,11 @@ import android.app.Activity;
4
4
  import android.content.res.Configuration;
5
5
  import android.view.View;
6
6
 
7
+ import com.reactnativenavigation.utils.LogKt;
7
8
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
8
9
  import com.reactnativenavigation.options.Options;
9
10
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
10
- import com.reactnativenavigation.utils.StatusBarUtils;
11
+ import com.reactnativenavigation.utils.SystemUiUtils;
11
12
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ReactViewCreator;
12
13
  import com.reactnativenavigation.viewcontrollers.child.ChildController;
13
14
  import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
@@ -127,8 +128,9 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
127
128
 
128
129
  @Override
129
130
  public int getTopInset() {
130
- int statusBarInset = resolveCurrentOptions(presenter.defaultOptions).statusBar.isHiddenOrDrawBehind() ? 0 : StatusBarUtils.getStatusBarHeight(getActivity());
131
- return statusBarInset + perform(getParentController(), 0, p -> p.getTopInset(this));
131
+ int statusBarInset = resolveCurrentOptions(presenter.defaultOptions).statusBar.isHiddenOrDrawBehind() ? 0 : SystemUiUtils.getStatusBarHeight(getActivity());
132
+ final Integer perform = perform(getParentController(), 0, p -> p.getTopInset(this));
133
+ return statusBarInset + perform;
132
134
  }
133
135
 
134
136
  @Override
@@ -137,14 +139,19 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
137
139
  }
138
140
 
139
141
  @Override
140
- protected WindowInsetsCompat applyWindowInsets(ViewController<?> view, WindowInsetsCompat insets) {
141
- final WindowInsetsCompat.Builder builder = new WindowInsetsCompat.Builder();
142
- final WindowInsetsCompat finalInsets = builder.setSystemWindowInsets(Insets.of(insets.getSystemWindowInsetLeft(),
143
- Math.max(insets.getSystemWindowInsetTop() - getTopInset(), 0),
144
- insets.getSystemWindowInsetRight(),
145
- Math.max(insets.getSystemWindowInsetBottom() - getBottomInset(), 0))).build();
146
- ViewCompat.onApplyWindowInsets(view.getView(), finalInsets);
147
- return finalInsets;
142
+ protected WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
143
+ ViewController<?> viewController = findController(view);
144
+ if (viewController == null || viewController.getView() == null) return insets;
145
+ final Insets keyboardInsets = insets.getInsets( WindowInsetsCompat.Type.ime());
146
+ final Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars() );
147
+ final int visibleNavBar = resolveCurrentOptions(presenter.defaultOptions).navigationBar.isVisible.isTrueOrUndefined()?1:0;
148
+ final WindowInsetsCompat finalInsets = new WindowInsetsCompat.Builder().setInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime(),
149
+ Insets.of(systemBarsInsets.left,
150
+ 0,
151
+ systemBarsInsets.right,
152
+ Math.max(visibleNavBar*systemBarsInsets.bottom,keyboardInsets.bottom))
153
+ ).build();
154
+ return ViewCompat.onApplyWindowInsets(viewController.getView(), finalInsets);
148
155
  }
149
156
 
150
157
  @Override
@@ -10,7 +10,7 @@ import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
10
10
  import com.reactnativenavigation.react.events.ComponentType;
11
11
  import com.reactnativenavigation.react.events.EventEmitter;
12
12
  import com.reactnativenavigation.utils.CoordinatorLayoutUtils;
13
- import com.reactnativenavigation.utils.StatusBarUtils;
13
+ import com.reactnativenavigation.utils.SystemUiUtils;
14
14
  import com.reactnativenavigation.viewcontrollers.child.ChildController;
15
15
  import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
16
16
  import com.reactnativenavigation.views.BehaviourDelegate;
@@ -72,7 +72,7 @@ public class ExternalComponentViewController extends ChildController<ExternalCom
72
72
 
73
73
  @Override
74
74
  public int getTopInset() {
75
- int statusBarInset = resolveCurrentOptions().statusBar.drawBehind.isTrue() ? 0 : StatusBarUtils.getStatusBarHeight(getActivity());
75
+ int statusBarInset = resolveCurrentOptions().statusBar.drawBehind.isTrue() ? 0 : SystemUiUtils.getStatusBarHeight(getActivity());
76
76
  return statusBarInset + perform(getParentController(), 0, p -> p.getTopInset(this));
77
77
  }
78
78
 
@@ -36,7 +36,7 @@ import com.reactnativenavigation.options.parsers.TypefaceLoader;
36
36
  import com.reactnativenavigation.utils.CollectionUtils;
37
37
  import com.reactnativenavigation.utils.ObjectUtils;
38
38
  import com.reactnativenavigation.utils.RenderChecker;
39
- import com.reactnativenavigation.utils.StatusBarUtils;
39
+ import com.reactnativenavigation.utils.SystemUiUtils;
40
40
  import com.reactnativenavigation.utils.UiUtils;
41
41
  import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
42
42
  import com.reactnativenavigation.viewcontrollers.stack.topbar.TopBarBackgroundViewController;
@@ -244,24 +244,38 @@ public class StackPresenter {
244
244
 
245
245
  private void applyStatusBarDrawBehindOptions(TopBarOptions topBarOptions, Options withDefault) {
246
246
  if (withDefault.statusBar.visible.isTrueOrUndefined() && withDefault.statusBar.drawBehind.isTrue()) {
247
- topBar.setTopPadding(StatusBarUtils.getStatusBarHeight(activity));
248
- topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)) + StatusBarUtils.getStatusBarHeightDp(activity));
247
+ topBar.setTopPadding(SystemUiUtils.getStatusBarHeight(activity));
248
+ topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)) + SystemUiUtils.getStatusBarHeightDp(activity));
249
+
249
250
  } else {
250
251
  topBar.setTopPadding(0);
251
252
  topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)));
252
253
  }
253
254
  }
254
-
255
- private void mergeStatusBarDrawBehindOptions(TopBarOptions topBarOptions, Options toMerge) {
256
- if (toMerge.statusBar.drawBehind.hasValue()) {
257
- if (toMerge.statusBar.visible.isTrueOrUndefined() && toMerge.statusBar.drawBehind.isTrue()) {
258
- topBar.setTopPadding(StatusBarUtils.getStatusBarHeight(activity));
259
- topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)) + StatusBarUtils.getStatusBarHeightDp(activity));
260
- } else {
261
- topBar.setTopPadding(0);
262
- topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)));
255
+
256
+ private void mergeStatusBarDrawBehindOptions(TopBarOptions topBarOptions, Options childOptions) {
257
+ if(childOptions.statusBar.visible.isTrueOrUndefined()){
258
+ if (childOptions.statusBar.drawBehind.hasValue()) {
259
+ if (childOptions.statusBar.drawBehind.isTrue()) {
260
+ topBar.setTopPadding(SystemUiUtils.getStatusBarHeight(activity));
261
+ topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)) + SystemUiUtils.getStatusBarHeightDp(activity));
262
+ } else {
263
+ topBar.setTopPadding(0);
264
+ topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)));
265
+ }
266
+ }
267
+ }else{
268
+ if (childOptions.statusBar.drawBehind.hasValue()) {
269
+ if (childOptions.statusBar.drawBehind.isFalseOrUndefined()) {
270
+ topBar.setTopPadding(SystemUiUtils.getStatusBarHeight(activity));
271
+ topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)) + SystemUiUtils.getStatusBarHeightDp(activity));
272
+ } else {
273
+ topBar.setTopPadding(0);
274
+ topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(activity)));
275
+ }
263
276
  }
264
277
  }
278
+
265
279
  }
266
280
 
267
281
  @Nullable
@@ -351,7 +365,6 @@ public class StackPresenter {
351
365
  perform(bottomTabsController, null, btc -> btc.getSetStackRootAnimation(appearingOptions))
352
366
  );
353
367
  }
354
-
355
368
  public void mergeChildOptions(Options toMerge, Options resolvedOptions, StackController stack, ViewController<?> child) {
356
369
  TopBarOptions topBar = toMerge.copy().topBar.mergeWithDefault(resolvedOptions.topBar).mergeWithDefault(defaultOptions.topBar);
357
370
  mergeOrientation(toMerge.layout.orientation);
@@ -485,16 +498,18 @@ public class StackPresenter {
485
498
  return result;
486
499
  }
487
500
 
488
- private void mergeTopBarOptions(TopBarOptions resolveOptions, Options options, StackController stack, ViewController<?> child) {
489
- TopBarOptions topBarOptions = options.topBar;
501
+ private void mergeTopBarOptions(TopBarOptions resolveOptions, Options toMerge, StackController stack,
502
+ ViewController<?> child) {
503
+ TopBarOptions topBarOptions = toMerge.topBar;
490
504
  final View component = child.getView();
491
- if (options.layout.direction.hasValue()) topBar.setLayoutDirection(options.layout.direction);
505
+ if (toMerge.layout.direction.hasValue()) topBar.setLayoutDirection(toMerge.layout.direction);
492
506
  if (topBarOptions.height.hasValue()) topBar.setHeight(topBarOptions.height.get());
493
507
  if (topBarOptions.elevation.hasValue()) topBar.setElevation(topBarOptions.elevation.get());
494
508
  if (topBarOptions.topMargin.hasValue() && topBar.getLayoutParams() instanceof MarginLayoutParams) {
495
509
  ((MarginLayoutParams) topBar.getLayoutParams()).topMargin = UiUtils.dpToPx(activity, topBarOptions.topMargin.get());
496
510
  }
497
- mergeStatusBarDrawBehindOptions(resolveOptions, options);
511
+ Options childOptions = stack.resolveChildOptions(child).mergeWith(toMerge).withDefaultOptions(defaultOptions);
512
+ mergeStatusBarDrawBehindOptions(resolveOptions, childOptions);
498
513
  if (topBarOptions.title.height.hasValue()) topBar.setTitleHeight(topBarOptions.title.height.get());
499
514
  if (topBarOptions.title.topMargin.hasValue()) topBar.setTitleTopMargin(topBarOptions.title.topMargin.get());
500
515
 
@@ -652,7 +667,7 @@ public class StackPresenter {
652
667
  private int getTopBarTopMargin(StackController stack, ViewController<?> child) {
653
668
  Options withDefault = stack.resolveChildOptions(child).withDefaultOptions(defaultOptions);
654
669
  int topMargin = UiUtils.dpToPx(activity, withDefault.topBar.topMargin.get(0));
655
- int statusBarInset = withDefault.statusBar.visible.isTrueOrUndefined() && !withDefault.statusBar.drawBehind.isTrue() ? StatusBarUtils.getStatusBarHeight(child.getActivity()) : 0;
670
+ int statusBarInset = withDefault.statusBar.visible.isTrueOrUndefined() && !withDefault.statusBar.drawBehind.isTrue() ? SystemUiUtils.getStatusBarHeight(child.getActivity()) : 0;
656
671
  return topMargin + statusBarInset;
657
672
  }
658
673
 
@@ -10,47 +10,52 @@ import android.view.View;
10
10
  import android.view.ViewGroup.MarginLayoutParams;
11
11
  import android.view.Window;
12
12
 
13
+ import androidx.core.content.ContextCompat;
14
+
13
15
  import com.reactnativenavigation.options.NavigationBarOptions;
14
16
  import com.reactnativenavigation.options.Options;
15
17
  import com.reactnativenavigation.options.OrientationOptions;
16
18
  import com.reactnativenavigation.options.StatusBarOptions;
17
19
  import com.reactnativenavigation.options.StatusBarOptions.TextColorScheme;
18
20
  import com.reactnativenavigation.options.params.Bool;
19
- import com.reactnativenavigation.utils.StatusBarUtils;
21
+ import com.reactnativenavigation.utils.SystemUiUtils;
20
22
  import com.reactnativenavigation.viewcontrollers.parent.ParentController;
21
23
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
22
24
 
23
- import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
24
-
25
25
  public class Presenter {
26
26
  private final Activity activity;
27
27
  private Options defaultOptions;
28
-
29
28
  public Presenter(Activity activity, Options defaultOptions) {
30
29
  this.activity = activity;
31
30
  this.defaultOptions = defaultOptions;
31
+
32
32
  }
33
33
 
34
34
  public void setDefaultOptions(Options defaultOptions) {
35
35
  this.defaultOptions = defaultOptions;
36
36
  }
37
37
 
38
- public void mergeOptions(View view, Options options) {
39
- mergeStatusBarOptions(view, options.statusBar);
40
- mergeNavigationBarOptions(options.navigationBar);
38
+ public Options getDefaultOptions() {
39
+ return defaultOptions;
40
+ }
41
+
42
+ public void mergeOptions(ViewController<?> viewController, Options options) {
43
+ final Options withDefaults = viewController.resolveCurrentOptions().copy().mergeWith(options).withDefaultOptions(defaultOptions);
44
+ mergeStatusBarOptions(viewController.getView(), withDefaults.statusBar);
45
+ mergeNavigationBarOptions(withDefaults.navigationBar);
41
46
  }
42
47
 
43
48
  public void applyOptions(ViewController view, Options options) {
44
49
  Options withDefaultOptions = options.copy().withDefaultOptions(defaultOptions);
45
50
  applyOrientation(withDefaultOptions.layout.orientation);
46
51
  applyViewOptions(view, withDefaultOptions);
47
- applyStatusBarOptions(withDefaultOptions);
52
+ applyStatusBarOptions(view, withDefaultOptions);
48
53
  applyNavigationBarOptions(withDefaultOptions.navigationBar);
49
54
  }
50
55
 
51
- public void onViewBroughtToFront(Options options) {
56
+ public void onViewBroughtToFront(ViewController<?> viewController, Options options) {
52
57
  Options withDefaultOptions = options.copy().withDefaultOptions(defaultOptions);
53
- applyStatusBarOptions(withDefaultOptions);
58
+ applyStatusBarOptions(viewController, withDefaultOptions);
54
59
  }
55
60
 
56
61
  private void applyOrientation(OrientationOptions options) {
@@ -73,7 +78,7 @@ public class Presenter {
73
78
  if (view instanceof Navigator) return;
74
79
 
75
80
  LayerDrawable ld = new LayerDrawable(new Drawable[]{new ColorDrawable(options.layout.backgroundColor.get())});
76
- int top = view.resolveCurrentOptions().statusBar.drawBehind.isTrue() ? 0 : StatusBarUtils.getStatusBarHeight(view.getActivity());
81
+ int top = view.resolveCurrentOptions().statusBar.drawBehind.isTrue() ? 0 : SystemUiUtils.getStatusBarHeight(view.getActivity());
77
82
  if (!(view instanceof ParentController)) {
78
83
  MarginLayoutParams lp = (MarginLayoutParams) view.getView().getLayoutParams();
79
84
  if (lp.topMargin != 0) top = 0;
@@ -83,37 +88,37 @@ public class Presenter {
83
88
  }
84
89
  }
85
90
 
86
- private void applyStatusBarOptions(Options options) {
91
+ private void applyStatusBarOptions(ViewController viewController, Options options) {
87
92
  StatusBarOptions statusBar = options.copy().withDefaultOptions(defaultOptions).statusBar;
88
93
  setStatusBarBackgroundColor(statusBar);
89
94
  setTextColorScheme(statusBar);
90
95
  setTranslucent(statusBar);
91
- setStatusBarVisible(statusBar.visible);
96
+ setStatusBarVisible(viewController, statusBar.visible);
92
97
  }
93
98
 
94
99
  private void setTranslucent(StatusBarOptions options) {
95
100
  Window window = activity.getWindow();
96
101
  if (options.translucent.isTrue()) {
97
- window.setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS);
98
- } else if (StatusBarUtils.isTranslucent(window)) {
99
- window.clearFlags(FLAG_TRANSLUCENT_STATUS);
102
+ SystemUiUtils.setStatusBarTranslucent(window);
103
+ } else if (SystemUiUtils.isTranslucent(window)) {
104
+ SystemUiUtils.clearStatusBarTranslucency(window);
100
105
  }
101
106
  }
102
107
 
103
- private void setStatusBarVisible(Bool visible) {
104
- View decorView = activity.getWindow().getDecorView();
105
- int flags = decorView.getSystemUiVisibility();
108
+ private void setStatusBarVisible(ViewController viewController, Bool visible) {
109
+ final View view = viewController.view != null ? viewController.view : activity.getWindow().getDecorView();
106
110
  if (visible.isFalse()) {
107
- flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
111
+ SystemUiUtils.hideStatusBar(activity.getWindow(), view);
108
112
  } else {
109
- flags &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
113
+ SystemUiUtils.showStatusBar(activity.getWindow(), view);
110
114
  }
111
- decorView.setSystemUiVisibility(flags);
112
115
  }
113
116
 
114
117
  private void setStatusBarBackgroundColor(StatusBarOptions statusBar) {
115
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && statusBar.backgroundColor.canApplyValue()) {
116
- activity.getWindow().setStatusBarColor(getStatusBarBackgroundColor(statusBar));
118
+ if (statusBar.backgroundColor.canApplyValue()) {
119
+ final int statusBarBackgroundColor = getStatusBarBackgroundColor(statusBar);
120
+ SystemUiUtils.setStatusBarColor(activity.getWindow(), statusBarBackgroundColor,
121
+ statusBar.translucent.isTrue());
117
122
  }
118
123
  }
119
124
 
@@ -133,20 +138,11 @@ public class Presenter {
133
138
  }
134
139
 
135
140
  private void setTextColorScheme(StatusBarOptions statusBar) {
136
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
137
-
138
141
  final View view = activity.getWindow().getDecorView();
139
142
  //View.post is a Workaround, added to solve internal Samsung
140
143
  //Android 9 issues. For more info see https://github.com/wix/react-native-navigation/pull/7231
141
- view.post(()->{
142
- int flags = view.getSystemUiVisibility();
143
- if (isDarkTextColorScheme(statusBar)) {
144
- flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
145
- } else {
146
- flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
147
- }
148
-
149
- view.setSystemUiVisibility(flags);
144
+ view.post(() -> {
145
+ SystemUiUtils.setStatusBarColorScheme(activity.getWindow(), view, isDarkTextColorScheme(statusBar));
150
146
  });
151
147
  }
152
148
 
@@ -154,12 +150,14 @@ public class Presenter {
154
150
  mergeStatusBarBackgroundColor(statusBar);
155
151
  mergeTextColorScheme(statusBar);
156
152
  mergeTranslucent(statusBar);
157
- mergeStatusBarVisible(view, statusBar.visible, statusBar.drawBehind);
153
+ mergeStatusBarVisible(view, statusBar.visible);
158
154
  }
159
155
 
160
156
  private void mergeStatusBarBackgroundColor(StatusBarOptions statusBar) {
161
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && statusBar.backgroundColor.hasValue()) {
162
- activity.getWindow().setStatusBarColor(getStatusBarBackgroundColor(statusBar));
157
+ if (statusBar.backgroundColor.hasValue()) {
158
+ final int statusBarBackgroundColor = getStatusBarBackgroundColor(statusBar);
159
+ SystemUiUtils.setStatusBarColor(activity.getWindow(), statusBarBackgroundColor,
160
+ statusBar.translucent.isTrue());
163
161
  }
164
162
  }
165
163
 
@@ -171,22 +169,19 @@ public class Presenter {
171
169
  private void mergeTranslucent(StatusBarOptions options) {
172
170
  Window window = activity.getWindow();
173
171
  if (options.translucent.isTrue()) {
174
- window.setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS);
175
- } else if (options.translucent.isFalse() && StatusBarUtils.isTranslucent(window)) {
176
- window.clearFlags(FLAG_TRANSLUCENT_STATUS);
172
+ SystemUiUtils.setStatusBarTranslucent(window);
173
+ } else if (options.translucent.isFalse() && SystemUiUtils.isTranslucent(window)) {
174
+ SystemUiUtils.clearStatusBarTranslucency(window);
177
175
  }
178
176
  }
179
177
 
180
- private void mergeStatusBarVisible(View view, Bool visible, Bool drawBehind) {
178
+ private void mergeStatusBarVisible(View view, Bool visible) {
181
179
  if (visible.hasValue()) {
182
- int flags = view.getSystemUiVisibility();
183
180
  if (visible.isTrue()) {
184
- flags &= ~View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN & ~View.SYSTEM_UI_FLAG_FULLSCREEN;
181
+ SystemUiUtils.showStatusBar(activity.getWindow(), view);
185
182
  } else {
186
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN;
183
+ SystemUiUtils.hideStatusBar(activity.getWindow(), view);
187
184
  }
188
- if (flags != view.getSystemUiVisibility()) view.requestLayout();
189
- view.setSystemUiVisibility(flags);
190
185
  }
191
186
  }
192
187
 
@@ -206,36 +201,22 @@ public class Presenter {
206
201
 
207
202
  private void applyNavigationBarVisibility(NavigationBarOptions options) {
208
203
  View decorView = activity.getWindow().getDecorView();
209
- int flags = decorView.getSystemUiVisibility();
210
- boolean defaultVisibility = (flags & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0;
211
- int hideNavigationBarFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
212
- if (options.isVisible.get(defaultVisibility)) {
213
- flags &= ~hideNavigationBarFlags;
204
+ if (options.isVisible.isTrueOrUndefined()) {
205
+ SystemUiUtils.showNavigationBar(activity.getWindow(), decorView);
214
206
  } else {
215
- flags |= hideNavigationBarFlags;
207
+ SystemUiUtils.hideNavigationBar(activity.getWindow(), decorView);
216
208
  }
217
- decorView.setSystemUiVisibility(flags);
218
209
  }
219
210
 
220
211
  private void setNavigationBarBackgroundColor(NavigationBarOptions navigationBar) {
221
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && navigationBar.backgroundColor.canApplyValue()) {
222
- int defaultColor = activity.getWindow().getNavigationBarColor();
223
- int color = navigationBar.backgroundColor.get(defaultColor);
224
- activity.getWindow().setNavigationBarColor(color);
225
- setNavigationBarButtonsColor(color);
226
- }
227
- }
212
+ int navigationBarDefaultColor = SystemUiUtils.INSTANCE.getNavigationBarDefaultColor();
213
+ navigationBarDefaultColor = navigationBarDefaultColor==-1?Color.BLACK:navigationBarDefaultColor;
214
+ if (navigationBar.backgroundColor.canApplyValue()) {
215
+ int color = navigationBar.backgroundColor.get(navigationBarDefaultColor);
216
+ SystemUiUtils.setNavigationBarBackgroundColor(activity.getWindow(), color, isColorLight(color));
217
+ }else{
218
+ SystemUiUtils.setNavigationBarBackgroundColor(activity.getWindow(), navigationBarDefaultColor, isColorLight(navigationBarDefaultColor));
228
219
 
229
- private void setNavigationBarButtonsColor(int color) {
230
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
231
- View decorView = activity.getWindow().getDecorView();
232
- int flags = decorView.getSystemUiVisibility();
233
- if (isColorLight(color)) {
234
- flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
235
- } else {
236
- flags &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
237
- }
238
- decorView.setSystemUiVisibility(flags);
239
220
  }
240
221
  }
241
222
 
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
4
4
  import android.content.Context;
5
5
  import android.view.MotionEvent;
6
6
  import android.view.ViewGroup;
7
+ import android.view.WindowInsets;
7
8
 
8
9
  import com.reactnativenavigation.options.ButtonOptions;
9
10
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
@@ -99,6 +100,7 @@ public class ComponentLayout extends CoordinatorLayout implements ReactComponent
99
100
  reactView.sendOnNavigationButtonPressed(button.id);
100
101
  }
101
102
 
103
+
102
104
  @Override
103
105
  public boolean onInterceptTouchEvent(MotionEvent ev) {
104
106
  return touchDelegate.onInterceptTouchEvent(ev);
@@ -13,7 +13,6 @@ import com.reactnativenavigation.options.SharedElementTransitionOptions
13
13
  import com.reactnativenavigation.utils.ViewUtils
14
14
  import kotlin.math.max
15
15
  import kotlin.math.roundToInt
16
- import android.animation.TypeEvaluator
17
16
 
18
17
  class ReactImageMatrixAnimator(from: View, to: View) : PropertyAnimatorCreator<ReactImageView>(from, to) {
19
18
  override fun shouldAnimateProperty(fromChild: ReactImageView, toChild: ReactImageView): Boolean {
@@ -39,7 +38,7 @@ class ReactImageMatrixAnimator(from: View, to: View) : PropertyAnimatorCreator<R
39
38
 
40
39
  to.layoutParams.width = max(from.width, to.width)
41
40
  to.layoutParams.height = max(from.height, to.height)
42
- return ObjectAnimator.ofObject(TypeEvaluator<Float> { fraction: Float, _: Any, _: Any ->
41
+ return ObjectAnimator.ofObject({ fraction: Float, _: Any, _: Any ->
43
42
  hierarchy.actualImageScaleType?.let {
44
43
  (hierarchy.actualImageScaleType as? InterpolatingScaleType)?.let {
45
44
  it.value = fraction
@@ -47,7 +46,7 @@ class ReactImageMatrixAnimator(from: View, to: View) : PropertyAnimatorCreator<R
47
46
  }
48
47
  }
49
48
  null
50
- }, 0, 1)
49
+ }, 0f, 1f)
51
50
  }
52
51
  }
53
52
 
@@ -47,7 +47,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
47
47
 
48
48
  @SuppressLint("ViewConstructor")
49
49
  public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAwareView {
50
- public final static int DEFAULT_TITLE_COLOR = Color.BLACK;
50
+ public final static int DEFAULT_TITLE_COLOR = Color.BLACK;
51
51
  public final static int DEFAULT_SUBTITLE_COLOR = Color.GRAY;
52
52
 
53
53
  private final TopBarCollapseBehavior collapsingBehavior;
@@ -75,7 +75,6 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
75
75
 
76
76
  private void createLayout() {
77
77
  setId(CompatUtils.generateViewId());
78
- setFitsSystemWindows(true);
79
78
  topTabs = createTopTabs();
80
79
  border = createBorder();
81
80
  LinearLayout content = createContentLayout();
@@ -21,7 +21,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
21
21
 
22
22
  import com.reactnativenavigation.options.params.Bool;
23
23
  import com.reactnativenavigation.utils.Functions;
24
- import com.reactnativenavigation.utils.StatusBarUtils;
24
+ import com.reactnativenavigation.utils.SystemUiUtils;
25
25
  import com.reactnativenavigation.utils.ViewUtils;
26
26
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
27
27
 
@@ -59,15 +59,16 @@ public abstract class BaseTest {
59
59
  when(res.getColor(ArgumentMatchers.anyInt(),any())).thenReturn(0x00000);
60
60
  }
61
61
 
62
- public void mockStatusBarUtils(int statusBarHeight,int statusBarHeightDp, Functions.Func block) {
63
- try (MockedStatic<StatusBarUtils> theMock = Mockito.mockStatic(StatusBarUtils.class)) {
62
+
63
+ public void mockSystemUiUtils(int statusBarHeight, int statusBarHeightDp, Functions.Func1<MockedStatic<SystemUiUtils>> mockedBlock) {
64
+ try (MockedStatic<SystemUiUtils> theMock = Mockito.mockStatic(SystemUiUtils.class)) {
64
65
  theMock.when(() -> {
65
- StatusBarUtils.getStatusBarHeight(any());
66
+ SystemUiUtils.getStatusBarHeight(any());
66
67
  }).thenReturn(statusBarHeight);
67
68
  theMock.when(() -> {
68
- StatusBarUtils.getStatusBarHeightDp(any());
69
+ SystemUiUtils.getStatusBarHeightDp(any());
69
70
  }).thenReturn(statusBarHeightDp);
70
- block.run();
71
+ mockedBlock.run(theMock);
71
72
  }
72
73
  }
73
74
 
@@ -1,41 +1,56 @@
1
1
  package com.reactnativenavigation.presentation;
2
2
 
3
3
  import android.app.Activity;
4
+ import android.view.View;
4
5
  import android.view.ViewGroup;
5
6
  import android.widget.FrameLayout;
6
7
 
7
8
  import com.reactnativenavigation.BaseTest;
8
9
  import com.reactnativenavigation.options.Options;
9
10
  import com.reactnativenavigation.options.params.Bool;
11
+ import com.reactnativenavigation.utils.SystemUiUtils;
10
12
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
13
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
11
14
 
12
15
  import org.junit.Test;
13
16
  import org.mockito.Mockito;
14
17
 
18
+ import static org.mockito.ArgumentMatchers.any;
19
+ import static org.mockito.ArgumentMatchers.eq;
20
+ import static org.mockito.Mockito.mock;
21
+ import static org.mockito.Mockito.times;
15
22
  import static org.mockito.Mockito.verify;
16
23
 
17
24
  public class PresenterTest extends BaseTest {
18
25
  private Presenter uut;
19
26
  private Activity activity;
27
+ private ViewController<ViewGroup> controller;
20
28
 
21
29
  @Override
22
30
  public void beforeEach() {
23
31
  super.beforeEach();
24
32
  activity = newActivity();
33
+ controller = mock(ViewController.class);
25
34
  uut = new Presenter(activity, Options.EMPTY);
26
35
  }
27
36
 
28
37
  @Test
29
- public void mergeStatusBarVisible_requestLayout() {
30
- ViewGroup spy = Mockito.spy(new FrameLayout(activity));
31
- Options options = new Options();
32
- options.statusBar.visible = new Bool(false);
38
+ public void mergeStatusBarVisible_callsShowHide() {
39
+ mockSystemUiUtils(1,1,(mockedStatic)->{
40
+ ViewGroup spy = Mockito.spy(new FrameLayout(activity));
41
+ Mockito.when(controller.getView()).thenReturn(spy);
42
+ Mockito.when(controller.resolveCurrentOptions()).thenReturn(Options.EMPTY);
43
+ Options options = new Options();
44
+ options.statusBar.visible = new Bool(false);
45
+ uut.mergeOptions(controller, options);
46
+ mockedStatic.verify(
47
+ ()-> SystemUiUtils.hideStatusBar(any(),eq(spy)),times(1));
48
+
49
+ options.statusBar.visible = new Bool(true);
50
+ uut.mergeOptions(controller, options);
51
+ mockedStatic.verify(
52
+ ()-> SystemUiUtils.showStatusBar(any(),eq(spy)),times(1));
53
+ });
33
54
 
34
- uut.mergeOptions(spy, options);
35
- verify(spy).requestLayout();
36
-
37
- // requested only if needed
38
- uut.mergeOptions(spy, options);
39
- verify(spy).requestLayout();
40
55
  }
41
56
  }
@@ -24,7 +24,7 @@ import com.reactnativenavigation.react.CommandListenerAdapter;
24
24
  import com.reactnativenavigation.react.events.EventEmitter;
25
25
  import com.reactnativenavigation.utils.ImageLoader;
26
26
  import com.reactnativenavigation.utils.OptionHelper;
27
- import com.reactnativenavigation.utils.StatusBarUtils;
27
+ import com.reactnativenavigation.utils.SystemUiUtils;
28
28
  import com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.BottomTabsAttacher;
29
29
  import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
30
30
  import com.reactnativenavigation.viewcontrollers.fakes.FakeParentController;
@@ -87,7 +87,7 @@ public class BottomTabsControllerTest extends BaseTest {
87
87
  childRegistry = new ChildControllersRegistry();
88
88
  eventEmitter = Mockito.mock(EventEmitter.class);
89
89
  prepareViewsForTests();
90
- StatusBarUtils.saveStatusBarHeight(63);
90
+ SystemUiUtils.saveStatusBarHeight(63);
91
91
  }
92
92
 
93
93
  @Test
@@ -184,6 +184,9 @@ public class BottomTabsControllerTest extends BaseTest {
184
184
  @Test
185
185
  public void applyChildOptions_bottomTabsOptionsAreClearedAfterApply() {
186
186
  ParentController<?> parent = Mockito.mock(ParentController.class);
187
+ Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
188
+ Mockito.when(parent.resolveChildOptions(child1)).thenReturn(Options.EMPTY);
189
+
187
190
  uut.setParentController(parent);
188
191
 
189
192
  child1.options.bottomTabsOptions.backgroundColor = new ThemeColour(new Colour(Color.RED));
@@ -506,6 +509,6 @@ public class BottomTabsControllerTest extends BaseTest {
506
509
  }
507
510
 
508
511
  private int getStatusBarHeight() {
509
- return StatusBarUtils.getStatusBarHeight(activity);
512
+ return SystemUiUtils.getStatusBarHeight(activity);
510
513
  }
511
514
  }
@@ -32,6 +32,7 @@ public class ChildControllerTest extends BaseTest {
32
32
  }
33
33
  };
34
34
  ParentController<?> parent = Mockito.mock(ParentController.class);
35
+ Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
35
36
  uut.setParentController(parent);
36
37
  }
37
38
 
@@ -55,7 +56,7 @@ public class ChildControllerTest extends BaseTest {
55
56
 
56
57
  Options options = new Options();
57
58
  uut.mergeOptions(options);
58
- verify(presenter).mergeOptions(uut.getView(), options);
59
+ verify(presenter).mergeOptions(uut, options);
59
60
  }
60
61
 
61
62
  @Test
@@ -11,7 +11,7 @@ import com.reactnativenavigation.mocks.TestComponentLayout;
11
11
  import com.reactnativenavigation.mocks.TestReactView;
12
12
  import com.reactnativenavigation.options.Options;
13
13
  import com.reactnativenavigation.options.params.Bool;
14
- import com.reactnativenavigation.utils.StatusBarUtils;
14
+ import com.reactnativenavigation.utils.SystemUiUtils;
15
15
  import com.reactnativenavigation.views.component.ComponentLayout;
16
16
 
17
17
  import org.assertj.core.api.Java6Assertions;
@@ -31,7 +31,7 @@ public class ComponentViewControllerTest extends BaseTest {
31
31
  public void beforeEach() {
32
32
  super.beforeEach();
33
33
  activity = newActivity();
34
- StatusBarUtils.saveStatusBarHeight(63);
34
+ SystemUiUtils.saveStatusBarHeight(63);
35
35
  view = Mockito.spy(new TestComponentLayout(activity, new TestReactView(activity)));
36
36
  parent = TestUtils.newStackController(activity).build();
37
37
  Presenter presenter = new Presenter(activity, new Options());
@@ -156,13 +156,13 @@ public class ComponentViewControllerTest extends BaseTest {
156
156
  public void getTopInset_returnsStatusBarHeight() {
157
157
  //noinspection ConstantConditions
158
158
  uut.setParentController(null);
159
- Java6Assertions.assertThat(uut.getTopInset()).isEqualTo(StatusBarUtils.getStatusBarHeight(activity));
159
+ Java6Assertions.assertThat(uut.getTopInset()).isEqualTo(SystemUiUtils.getStatusBarHeight(activity));
160
160
  }
161
161
 
162
162
  @Test
163
163
  public void getTopInset_resolveWithParent() {
164
164
  Java6Assertions
165
- .assertThat(uut.getTopInset()).isEqualTo(StatusBarUtils.getStatusBarHeight(activity) + parent.getTopInset(uut));
165
+ .assertThat(uut.getTopInset()).isEqualTo(SystemUiUtils.getStatusBarHeight(activity) + parent.getTopInset(uut));
166
166
  }
167
167
 
168
168
  @Test
@@ -264,6 +264,8 @@ public class ParentControllerTest extends BaseTest {
264
264
  @Test
265
265
  public void getTopInsetForChild() {
266
266
  ParentController<?> parent = Mockito.mock(ParentController.class);
267
+ Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
268
+
267
269
  when(parent.getTopInset(any())).thenReturn(123);
268
270
  uut.setParentController(parent);
269
271
 
@@ -280,6 +282,8 @@ public class ParentControllerTest extends BaseTest {
280
282
  @Test
281
283
  public void getBottomInsetForChild() {
282
284
  ParentController<?> parent = Mockito.mock(ParentController.class);
285
+ Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
286
+
283
287
  when(parent.getBottomInset(any())).thenReturn(123);
284
288
  uut.setParentController(parent);
285
289
 
@@ -2,6 +2,7 @@ package com.reactnativenavigation.viewcontrollers.sidemenu;
2
2
 
3
3
  import android.app.Activity;
4
4
  import android.content.res.Resources;
5
+ import android.graphics.Path;
5
6
  import android.util.TypedValue;
6
7
  import android.view.Gravity;
7
8
  import android.view.View;
@@ -55,6 +56,7 @@ public class SideMenuControllerTest extends BaseTest {
55
56
 
56
57
  @Override
57
58
  public void beforeEach() {
59
+ super.beforeEach();
58
60
  activity = createActivity();
59
61
 
60
62
  childRegistry = new ChildControllersRegistry();
@@ -72,6 +74,7 @@ public class SideMenuControllerTest extends BaseTest {
72
74
  };
73
75
  uut.setCenterController(center);
74
76
  parent = mock(ParentController.class);
77
+ Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
75
78
  uut.setParentController(parent);
76
79
  }
77
80
 
@@ -118,12 +121,12 @@ public class SideMenuControllerTest extends BaseTest {
118
121
 
119
122
  @Test
120
123
  public void onViewAppeared() {
121
- ViewController<?> left = spy(this.left);
124
+ ViewController left = spy(this.left);
122
125
  ViewGroup leftView = spy(left.getView());
123
126
  when(left.findController(leftView)).thenReturn(left);
124
127
  Mockito.doReturn(leftView).when(left).getView();
125
128
 
126
- ViewController<?> right = spy(this.right);
129
+ ViewController right = spy(this.right);
127
130
  ViewGroup rightView = spy(right.getView());
128
131
  when(right.findController(rightView)).thenReturn(right);
129
132
  Mockito.doReturn(rightView).when(right).getView();
@@ -369,6 +372,7 @@ public class SideMenuControllerTest extends BaseTest {
369
372
  @Test
370
373
  public void onMeasureChild_topInsetsAreApplied() {
371
374
  setLeftRight(spy(left), spy(right));
375
+ idleMainLooper();
372
376
  uut.applyTopInset();
373
377
  forEach(uut.getChildControllers(), c -> verify(c).applyTopInset());
374
378
  }
@@ -61,7 +61,7 @@ class StackControllerTest : BaseTest() {
61
61
  eventEmitter = mock()
62
62
  backButtonHelper = spy(BackButtonHelper())
63
63
  activity = newActivity()
64
- StatusBarUtils.saveStatusBarHeight(63)
64
+ SystemUiUtils.saveStatusBarHeight(63)
65
65
  animator = spy(StackAnimator(activity))
66
66
  childRegistry = ChildControllersRegistry()
67
67
  presenter = spy(StackPresenter(
@@ -1089,7 +1089,7 @@ class StackControllerTest : BaseTest() {
1089
1089
  disablePushAnimation(child1)
1090
1090
  uut.push(child1, CommandListenerAdapter())
1091
1091
  ShadowLooper.idleMainLooper()
1092
- assertThat(ViewUtils.topMargin(uut.topBar)).isEqualTo(StatusBarUtils.getStatusBarHeight(activity))
1092
+ assertThat(ViewUtils.topMargin(uut.topBar)).isEqualTo(SystemUiUtils.getStatusBarHeight(activity))
1093
1093
  }
1094
1094
 
1095
1095
  @Test
@@ -945,7 +945,7 @@ class StackPresenterTest : BaseTest() {
945
945
  statusBar.drawBehind = Bool(true)
946
946
  }
947
947
  Mockito.`when`(child.resolveCurrentOptions()).thenReturn(options)
948
- mockStatusBarUtils(statusBarHeight, statusBarHeightDp) {
948
+ mockSystemUiUtils(statusBarHeight, statusBarHeightDp) {
949
949
  uut.applyChildOptions(Options.EMPTY.copy().apply {
950
950
  topBar.height = Number(topBarHeightDp)
951
951
  }, parent, child)
@@ -961,7 +961,7 @@ class StackPresenterTest : BaseTest() {
961
961
  val statusBarHeightDp = 20
962
962
  val topBarHeightDp = 100
963
963
 
964
- mockStatusBarUtils(statusBarHeight, statusBarHeightDp) {
964
+ mockSystemUiUtils(statusBarHeight, statusBarHeightDp) {
965
965
  uut.mergeChildOptions(Options.EMPTY.copy().apply {
966
966
  topBar.height = Number(topBarHeightDp)
967
967
  statusBar.drawBehind = Bool(true)
@@ -978,7 +978,7 @@ class StackPresenterTest : BaseTest() {
978
978
  val statusBarHeightDp = 20
979
979
  val topBarHeightDp = 100
980
980
 
981
- mockStatusBarUtils(statusBarHeight, statusBarHeightDp) {
981
+ mockSystemUiUtils(statusBarHeight, statusBarHeightDp) {
982
982
  uut.mergeChildOptions(Options.EMPTY.copy().apply {
983
983
  topBar.height = Number(topBarHeightDp)
984
984
  statusBar.drawBehind = Bool(false)
@@ -31,6 +31,7 @@ import org.robolectric.Shadows;
31
31
  import java.lang.reflect.Field;
32
32
 
33
33
  import static org.assertj.core.api.Java6Assertions.assertThat;
34
+ import static org.mockito.ArgumentMatchers.any;
34
35
  import static org.mockito.Mockito.mock;
35
36
  import static org.mockito.Mockito.spy;
36
37
  import static org.mockito.Mockito.times;
@@ -51,7 +52,9 @@ public class ViewControllerTest extends BaseTest {
51
52
  activity = newActivity();
52
53
  childRegistry = new ChildControllersRegistry();
53
54
  uut = new SimpleViewController(activity, childRegistry, "uut", new Options());
54
- uut.setParentController(mock(ParentController.class));
55
+ final ParentController<?> parent = mock(ParentController.class);
56
+ uut.setParentController(parent);
57
+ Mockito.when(parent.resolveChildOptions(any())).thenReturn(Options.EMPTY);
55
58
  }
56
59
 
57
60
  @Test
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-navigation",
3
- "version": "7.23.1-snapshot.421",
3
+ "version": "7.23.1-snapshot.434",
4
4
  "description": "React Native Navigation - truly native navigation for iOS and Android",
5
5
  "license": "MIT",
6
6
  "nativePackage": true,
@@ -102,7 +102,7 @@
102
102
  "metro-react-native-babel-preset": "0.66.2",
103
103
  "prettier": "2.1.2",
104
104
  "react": "17.0.2",
105
- "react-native": "0.66.2",
105
+ "react-native": "0.66.3",
106
106
  "react-native-fast-image": "^8.3.4",
107
107
  "react-native-gesture-handler": "^1.6.1",
108
108
  "react-native-reanimated": "2.3.0-beta.2",
@@ -1,39 +0,0 @@
1
- package com.reactnativenavigation.utils
2
-
3
- import android.content.Context
4
- import android.os.Build
5
- import android.view.Window
6
- import android.view.WindowManager
7
-
8
- object StatusBarUtils {
9
- private const val STATUS_BAR_HEIGHT_M = 24
10
- private const val STATUS_BAR_HEIGHT_L = 25
11
- private var statusBarHeight = -1
12
- @JvmStatic
13
- fun saveStatusBarHeight(height: Int) {
14
- statusBarHeight = height
15
- }
16
- @JvmStatic
17
- fun getStatusBarHeight(context: Context): Int {
18
- if (statusBarHeight > 0) {
19
- return statusBarHeight
20
- }
21
- val resources = context.resources
22
- val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
23
- statusBarHeight = if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else UiUtils.dpToPx(
24
- context,
25
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) STATUS_BAR_HEIGHT_M else STATUS_BAR_HEIGHT_L
26
- )
27
- return statusBarHeight
28
- }
29
- @JvmStatic
30
- fun getStatusBarHeightDp(context: Context): Int {
31
- return UiUtils.pxToDp(context, getStatusBarHeight(context).toFloat())
32
- .toInt()
33
- }
34
- @JvmStatic
35
- fun isTranslucent(window: Window): Boolean {
36
- val lp = window.attributes
37
- return lp != null && lp.flags and WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS == WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
38
- }
39
- }