react-native-edge-to-edge 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/android/src/main/java/com/zoontek/rnedgetoedge/RNEdgeToEdgeModuleImpl.kt +23 -38
- package/android/src/main/res/values/colors.xml +1 -3
- package/android/src/main/res/values/styles.xml +1 -1
- package/android/src/main/res/values-night-v27/styles.xml +7 -0
- package/android/src/main/res/values-v27/colors.xml +5 -0
- package/android/src/main/res/values-v27/styles.xml +5 -2
- package/android/src/main/res/values-v29/colors.xml +4 -0
- package/android/src/main/res/values-v29/styles.xml +0 -1
- package/android/src/main/res/values-v30/styles.xml +0 -1
- package/android/src/newarch/com/zoontek/rnedgetoedge/RNEdgeToEdgeModule.kt +17 -6
- package/android/src/oldarch/com/zoontek/rnedgetoedge/RNBarsModule.kt +17 -6
- package/dist/commonjs/NativeRNEdgeToEdge.web.js +10 -0
- package/dist/commonjs/NativeRNEdgeToEdge.web.js.map +1 -0
- package/dist/module/NativeRNEdgeToEdge.web.js +6 -0
- package/dist/module/NativeRNEdgeToEdge.web.js.map +1 -0
- package/dist/typescript/NativeRNEdgeToEdge.web.d.ts +5 -0
- package/dist/typescript/NativeRNEdgeToEdge.web.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/NativeRNEdgeToEdge.web.ts +5 -0
- package/android/src/main/res/values-v26/styles.xml +0 -6
package/README.md
CHANGED
|
@@ -25,7 +25,9 @@ It is supporting the **latest version**, and the **two previous minor series**.
|
|
|
25
25
|
|
|
26
26
|
### Android 15
|
|
27
27
|
|
|
28
|
-
With the upcoming release of Android 15, Google is introducing a significant change: apps targeting SDK 35 [will have edge-to-edge enforcement](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge).
|
|
28
|
+
With the upcoming release of Android 15, Google is introducing a significant change: apps targeting SDK 35 [will have edge-to-edge enforcement](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge). Google is _likely_ to mandate that app updates on the Play Store target SDK 35 starting on August 31, 2025. This assumption is based on the [previous years' requirements following a similar timeline](https://support.google.com/googleplay/android-developer/answer/11926878?sjid=11853000253346477363-EU#zippy=%2Care-there-any-exceptions-for-existing-apps-targeting-api-or-below:~:text=App%20update%20requirements).
|
|
29
|
+
|
|
30
|
+
Currently, new React Native projects target SDK 34.
|
|
29
31
|
|
|
30
32
|
### Immersive mode
|
|
31
33
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
package com.zoontek.rnedgetoedge
|
|
2
2
|
|
|
3
|
-
import android.app.Activity
|
|
4
3
|
import android.content.res.Configuration
|
|
5
4
|
import android.graphics.Color
|
|
6
5
|
import android.os.Build
|
|
7
|
-
import android.
|
|
6
|
+
import android.os.Handler
|
|
7
|
+
import android.os.Looper
|
|
8
8
|
import android.view.WindowManager
|
|
9
9
|
|
|
10
10
|
import androidx.core.content.ContextCompat
|
|
@@ -13,36 +13,33 @@ import androidx.core.view.WindowInsetsCompat
|
|
|
13
13
|
import androidx.core.view.WindowInsetsControllerCompat
|
|
14
14
|
|
|
15
15
|
import com.facebook.common.logging.FLog
|
|
16
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
16
17
|
import com.facebook.react.bridge.ReadableMap
|
|
17
18
|
import com.facebook.react.common.ReactConstants
|
|
18
19
|
|
|
19
20
|
object RNEdgeToEdgeModuleImpl {
|
|
20
21
|
const val NAME = "RNEdgeToEdge"
|
|
21
|
-
private var isInitialHostResume = true
|
|
22
22
|
|
|
23
|
-
fun
|
|
24
|
-
|
|
25
|
-
return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.")
|
|
26
|
-
}
|
|
23
|
+
private fun applyEdgeToEdge(reactContext: ReactApplicationContext) {
|
|
24
|
+
val activity = reactContext.currentActivity
|
|
25
|
+
?: return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.")
|
|
27
26
|
|
|
28
27
|
activity.runOnUiThread {
|
|
29
28
|
val window = activity.window
|
|
30
29
|
val view = window.decorView
|
|
31
30
|
val context = view.context
|
|
32
31
|
|
|
33
|
-
val isDarkMode =
|
|
34
|
-
view.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
|
|
35
|
-
Configuration.UI_MODE_NIGHT_YES
|
|
36
|
-
|
|
37
32
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
38
33
|
|
|
39
34
|
window.statusBarColor = Color.TRANSPARENT
|
|
35
|
+
window.navigationBarColor = ContextCompat.getColor(context, R.color.navigationBarColor)
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
val isDarkMode =
|
|
38
|
+
view.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
|
|
39
|
+
Configuration.UI_MODE_NIGHT_YES
|
|
40
|
+
|
|
41
|
+
WindowInsetsControllerCompat(window, view).run {
|
|
42
|
+
isAppearanceLightNavigationBars = !isDarkMode
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
@@ -50,38 +47,26 @@ object RNEdgeToEdgeModuleImpl {
|
|
|
50
47
|
window.isNavigationBarContrastEnforced = true
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
WindowInsetsControllerCompat(window, view).run {
|
|
54
|
-
if (isInitialHostResume) {
|
|
55
|
-
val typedValue = TypedValue()
|
|
56
|
-
|
|
57
|
-
isAppearanceLightStatusBars = activity
|
|
58
|
-
.theme
|
|
59
|
-
.resolveAttribute(android.R.attr.windowLightStatusBar, typedValue, true) &&
|
|
60
|
-
typedValue.data != 0
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
isInitialHostResume = false
|
|
64
|
-
isAppearanceLightNavigationBars = !isDarkMode
|
|
65
|
-
}
|
|
66
|
-
|
|
67
50
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
68
51
|
window.attributes.layoutInDisplayCutoutMode = when {
|
|
69
|
-
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ->
|
|
70
|
-
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
|
52
|
+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
|
71
53
|
else -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
|
72
54
|
}
|
|
73
55
|
}
|
|
74
56
|
}
|
|
75
57
|
}
|
|
76
58
|
|
|
77
|
-
fun
|
|
78
|
-
|
|
59
|
+
fun onHostResume(reactContext: ReactApplicationContext) {
|
|
60
|
+
applyEdgeToEdge(reactContext)
|
|
79
61
|
}
|
|
80
62
|
|
|
81
|
-
fun
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
63
|
+
fun onConfigChange(reactContext: ReactApplicationContext) {
|
|
64
|
+
Handler(Looper.getMainLooper()).postDelayed({ applyEdgeToEdge(reactContext) }, 100)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fun setSystemBarsConfig(reactContext: ReactApplicationContext, config: ReadableMap) {
|
|
68
|
+
val activity = reactContext.currentActivity
|
|
69
|
+
?: return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.")
|
|
85
70
|
|
|
86
71
|
val statusBarHidden =
|
|
87
72
|
config.takeIf { it.hasKey("statusBarHidden") }?.getBoolean("statusBarHidden")
|
|
@@ -2,7 +2,5 @@
|
|
|
2
2
|
<resources>
|
|
3
3
|
<!-- https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/remote_color_resources_res/values/colors.xml;l=67 -->
|
|
4
4
|
<!-- https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/res/color/system_bar_background_semi_transparent.xml -->
|
|
5
|
-
<color name="
|
|
6
|
-
<!-- https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/com/android/internal/policy/DecorView.java;l=142 -->
|
|
7
|
-
<color name="systemBarLightScrim">#e6ffffff</color>
|
|
5
|
+
<color name="navigationBarColor">#801b1b1b</color>
|
|
8
6
|
</resources>
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
<item name="android:fitsSystemWindows">false</item>
|
|
9
9
|
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
10
10
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
|
11
|
+
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
11
12
|
</style>
|
|
12
13
|
|
|
13
14
|
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.Common">
|
|
14
|
-
<item name="android:navigationBarColor">@color/systemBarDarkScrim</item>
|
|
15
15
|
</style>
|
|
16
16
|
</resources>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<resources>
|
|
3
|
+
<style name="Theme.EdgeToEdge.Base" parent="Theme.AppCompat.DayNight.NoActionBar">
|
|
4
|
+
<item name="android:windowLightStatusBar">false</item>
|
|
5
|
+
<item name="android:windowLightNavigationBar">false</item>
|
|
6
|
+
</style>
|
|
7
|
+
</resources>
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<resources>
|
|
3
|
+
<style name="Theme.EdgeToEdge.Base" parent="Theme.AppCompat.DayNight.NoActionBar">
|
|
4
|
+
<item name="android:windowLightStatusBar">true</item>
|
|
5
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
6
|
+
</style>
|
|
7
|
+
|
|
3
8
|
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.Common">
|
|
4
9
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
5
|
-
<item name="android:navigationBarColor">@color/systemBarLightScrim</item>
|
|
6
|
-
<item name="android:windowLightNavigationBar">true</item>
|
|
7
10
|
</style>
|
|
8
11
|
</resources>
|
|
@@ -4,6 +4,5 @@
|
|
|
4
4
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
5
5
|
<item name="android:enforceStatusBarContrast">false</item>
|
|
6
6
|
<item name="android:enforceNavigationBarContrast">true</item>
|
|
7
|
-
<item name="android:navigationBarColor">@android:color/transparent</item>
|
|
8
7
|
</style>
|
|
9
8
|
</resources>
|
|
@@ -4,6 +4,5 @@
|
|
|
4
4
|
<item name="android:windowLayoutInDisplayCutoutMode">always</item>
|
|
5
5
|
<item name="android:enforceStatusBarContrast">false</item>
|
|
6
6
|
<item name="android:enforceNavigationBarContrast">true</item>
|
|
7
|
-
<item name="android:navigationBarColor">@android:color/transparent</item>
|
|
8
7
|
</style>
|
|
9
8
|
</resources>
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
package com.zoontek.rnedgetoedge
|
|
2
2
|
|
|
3
|
+
import android.content.BroadcastReceiver
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.content.IntentFilter
|
|
7
|
+
|
|
3
8
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
4
9
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
10
|
import com.facebook.react.bridge.ReadableMap
|
|
6
11
|
import com.facebook.react.module.annotations.ReactModule
|
|
7
12
|
|
|
8
13
|
@ReactModule(name = RNEdgeToEdgeModuleImpl.NAME)
|
|
9
|
-
class RNEdgeToEdgeModule(reactContext: ReactApplicationContext
|
|
14
|
+
class RNEdgeToEdgeModule(reactContext: ReactApplicationContext) :
|
|
10
15
|
NativeRNEdgeToEdgeSpec(reactContext), LifecycleEventListener {
|
|
11
16
|
|
|
17
|
+
private val configChangeReceiver = object : BroadcastReceiver() {
|
|
18
|
+
override fun onReceive(context: Context, intent: Intent) {
|
|
19
|
+
RNEdgeToEdgeModuleImpl.onConfigChange(reactContext)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
init {
|
|
24
|
+
reactApplicationContext.registerReceiver(configChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED))
|
|
13
25
|
reactApplicationContext.addLifecycleEventListener(this)
|
|
14
26
|
}
|
|
15
27
|
|
|
16
28
|
override fun invalidate() {
|
|
29
|
+
reactApplicationContext.unregisterReceiver(configChangeReceiver)
|
|
17
30
|
reactApplicationContext.removeLifecycleEventListener(this)
|
|
18
31
|
}
|
|
19
32
|
|
|
@@ -22,16 +35,14 @@ class RNEdgeToEdgeModule(reactContext: ReactApplicationContext?) :
|
|
|
22
35
|
}
|
|
23
36
|
|
|
24
37
|
override fun onHostResume() {
|
|
25
|
-
RNEdgeToEdgeModuleImpl.onHostResume(
|
|
38
|
+
RNEdgeToEdgeModuleImpl.onHostResume(reactApplicationContext)
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
override fun onHostPause() {}
|
|
29
42
|
|
|
30
|
-
override fun onHostDestroy() {
|
|
31
|
-
RNEdgeToEdgeModuleImpl.onHostDestroy()
|
|
32
|
-
}
|
|
43
|
+
override fun onHostDestroy() {}
|
|
33
44
|
|
|
34
45
|
override fun setSystemBarsConfig(config: ReadableMap) {
|
|
35
|
-
RNEdgeToEdgeModuleImpl.setSystemBarsConfig(
|
|
46
|
+
RNEdgeToEdgeModuleImpl.setSystemBarsConfig(reactApplicationContext, config)
|
|
36
47
|
}
|
|
37
48
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
package com.zoontek.rnedgetoedge
|
|
2
2
|
|
|
3
|
+
import android.content.BroadcastReceiver
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.content.IntentFilter
|
|
7
|
+
|
|
3
8
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
4
9
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
10
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
@@ -8,14 +13,22 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
8
13
|
import com.facebook.react.module.annotations.ReactModule
|
|
9
14
|
|
|
10
15
|
@ReactModule(name = RNEdgeToEdgeModuleImpl.NAME)
|
|
11
|
-
class RNEdgeToEdgeModule(reactContext: ReactApplicationContext
|
|
16
|
+
class RNEdgeToEdgeModule(reactContext: ReactApplicationContext) :
|
|
12
17
|
ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
|
|
13
18
|
|
|
19
|
+
private val configChangeReceiver = object : BroadcastReceiver() {
|
|
20
|
+
override fun onReceive(context: Context, intent: Intent) {
|
|
21
|
+
RNEdgeToEdgeModuleImpl.onConfigChange(reactContext)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
14
25
|
init {
|
|
26
|
+
reactApplicationContext.registerReceiver(configChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED))
|
|
15
27
|
reactApplicationContext.addLifecycleEventListener(this)
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
override fun invalidate() {
|
|
31
|
+
reactApplicationContext.unregisterReceiver(configChangeReceiver)
|
|
19
32
|
reactApplicationContext.removeLifecycleEventListener(this)
|
|
20
33
|
}
|
|
21
34
|
|
|
@@ -24,17 +37,15 @@ class RNEdgeToEdgeModule(reactContext: ReactApplicationContext?) :
|
|
|
24
37
|
}
|
|
25
38
|
|
|
26
39
|
override fun onHostResume() {
|
|
27
|
-
RNEdgeToEdgeModuleImpl.onHostResume(
|
|
40
|
+
RNEdgeToEdgeModuleImpl.onHostResume(reactApplicationContext)
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
override fun onHostPause() {}
|
|
31
44
|
|
|
32
|
-
override fun onHostDestroy() {
|
|
33
|
-
RNEdgeToEdgeModuleImpl.onHostDestroy()
|
|
34
|
-
}
|
|
45
|
+
override fun onHostDestroy() {}
|
|
35
46
|
|
|
36
47
|
@ReactMethod
|
|
37
48
|
fun setSystemBarsConfig(config: ReadableMap) {
|
|
38
|
-
RNEdgeToEdgeModuleImpl.setSystemBarsConfig(
|
|
49
|
+
RNEdgeToEdgeModuleImpl.setSystemBarsConfig(reactApplicationContext, config)
|
|
39
50
|
}
|
|
40
51
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["setSystemBarsConfig"],"sourceRoot":"../../src","sources":["NativeRNEdgeToEdge.web.ts"],"mappings":";;;;;;iCAEe;EACbA,mBAAmBA,CAAA,EAAG,CAAC;AACzB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["setSystemBarsConfig"],"sourceRoot":"../../src","sources":["NativeRNEdgeToEdge.web.ts"],"mappings":";;AAEA,eAAe;EACbA,mBAAmBA,CAAA,EAAG,CAAC;AACzB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeRNEdgeToEdge.web.d.ts","sourceRoot":"","sources":["../../src/NativeRNEdgeToEdge.web.ts"],"names":[],"mappings":";;;AAEA,wBAEiB"}
|
package/package.json
CHANGED