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.
- package/lib/android/app/build.gradle +3 -3
- package/lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java +5 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalFrameLayout.kt +3 -3
- package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalViewManager.kt +11 -8
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +168 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +12 -16
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +18 -11
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java +2 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +33 -18
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +52 -71
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/component/ComponentLayout.java +2 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/ReactImageMatrixAnimator.kt +2 -3
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/TopBar.java +1 -2
- package/lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java +7 -6
- package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/PresenterTest.java +25 -10
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.java +6 -3
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java +2 -1
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewControllerTest.java +4 -4
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/parent/ParentControllerTest.java +4 -0
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/sidemenu/SideMenuControllerTest.java +6 -2
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.kt +2 -2
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenterTest.kt +3 -3
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewControllerTest.java +4 -1
- package/package.json +2 -2
- 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.
|
|
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
|
|
181
|
-
implementation 'androidx.annotation:annotation:1.
|
|
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.
|
|
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,
|
|
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
|
}
|
package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalFrameLayout.kt
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
14
|
+
SystemUiUtils.isTranslucent(it)
|
|
15
15
|
} ?: false
|
|
16
|
-
topMargin = if (translucent) 0 else
|
|
16
|
+
topMargin = if (translucent) 0 else SystemUiUtils.getStatusBarHeight(context.currentActivity)
|
|
17
17
|
})
|
|
18
18
|
}
|
|
19
19
|
}
|
package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalViewManager.kt
CHANGED
|
@@ -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.
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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(
|
|
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
|
-
|
|
97
|
-
|
|
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.
|
|
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 :
|
|
131
|
-
|
|
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
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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.
|
|
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 :
|
|
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.
|
|
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(
|
|
248
|
-
topBar.setHeight(topBarOptions.height.get(UiUtils.getTopBarHeightDp(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
|
|
256
|
-
if
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
|
489
|
-
|
|
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 (
|
|
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
|
-
|
|
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() ?
|
|
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.
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
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 :
|
|
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
|
-
|
|
98
|
-
} else if (
|
|
99
|
-
|
|
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
|
|
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
|
-
|
|
111
|
+
SystemUiUtils.hideStatusBar(activity.getWindow(), view);
|
|
108
112
|
} else {
|
|
109
|
-
|
|
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 (
|
|
116
|
-
|
|
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
|
-
|
|
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
|
|
153
|
+
mergeStatusBarVisible(view, statusBar.visible);
|
|
158
154
|
}
|
|
159
155
|
|
|
160
156
|
private void mergeStatusBarBackgroundColor(StatusBarOptions statusBar) {
|
|
161
|
-
if (
|
|
162
|
-
|
|
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
|
-
|
|
175
|
-
} else if (options.translucent.isFalse() &&
|
|
176
|
-
|
|
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
|
|
178
|
+
private void mergeStatusBarVisible(View view, Bool visible) {
|
|
181
179
|
if (visible.hasValue()) {
|
|
182
|
-
int flags = view.getSystemUiVisibility();
|
|
183
180
|
if (visible.isTrue()) {
|
|
184
|
-
|
|
181
|
+
SystemUiUtils.showStatusBar(activity.getWindow(), view);
|
|
185
182
|
} else {
|
|
186
|
-
|
|
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
|
-
|
|
210
|
-
|
|
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
|
-
|
|
207
|
+
SystemUiUtils.hideNavigationBar(activity.getWindow(), decorView);
|
|
216
208
|
}
|
|
217
|
-
decorView.setSystemUiVisibility(flags);
|
|
218
209
|
}
|
|
219
210
|
|
|
220
211
|
private void setNavigationBarBackgroundColor(NavigationBarOptions navigationBar) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
|
package/lib/android/app/src/main/java/com/reactnativenavigation/views/component/ComponentLayout.java
CHANGED
|
@@ -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(
|
|
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
|
-
},
|
|
49
|
+
}, 0f, 1f)
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
52
|
|
package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/TopBar.java
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
66
|
+
SystemUiUtils.getStatusBarHeight(any());
|
|
66
67
|
}).thenReturn(statusBarHeight);
|
|
67
68
|
theMock.when(() -> {
|
|
68
|
-
|
|
69
|
+
SystemUiUtils.getStatusBarHeightDp(any());
|
|
69
70
|
}).thenReturn(statusBarHeightDp);
|
|
70
|
-
|
|
71
|
+
mockedBlock.run(theMock);
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
|
package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/PresenterTest.java
CHANGED
|
@@ -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
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
}
|