react-native-edge-to-edge 1.1.3 → 1.3.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 +75 -73
- package/android/src/main/java/com/zoontek/rnedgetoedge/EdgeToEdgeModuleImpl.kt +59 -15
- package/android/src/main/java/com/zoontek/rnedgetoedge/EdgeToEdgePackage.kt +9 -12
- package/android/src/main/res/values/attrs.xml +5 -0
- package/android/src/main/res/values/public.xml +6 -0
- package/android/src/main/res/values/styles.xml +52 -6
- package/android/src/main/res/values-v27/colors.xml +1 -2
- package/android/src/main/res/values-v27/styles.xml +18 -3
- package/android/src/main/res/values-v29/styles.xml +27 -6
- package/android/src/main/res/values-v30/styles.xml +27 -6
- package/dist/commonjs/SystemBars.js +18 -7
- package/dist/commonjs/SystemBars.js.map +1 -1
- package/dist/commonjs/expo.js +17 -4
- package/dist/commonjs/expo.js.map +1 -1
- package/dist/commonjs/specs/NativeEdgeToEdgeModule.js.map +1 -1
- package/dist/module/SystemBars.js +18 -7
- package/dist/module/SystemBars.js.map +1 -1
- package/dist/module/expo.js +17 -4
- package/dist/module/expo.js.map +1 -1
- package/dist/module/specs/NativeEdgeToEdgeModule.js.map +1 -1
- package/dist/typescript/SystemBars.d.ts.map +1 -1
- package/dist/typescript/expo.d.ts +6 -4
- package/dist/typescript/expo.d.ts.map +1 -1
- package/dist/typescript/specs/NativeEdgeToEdgeModule.d.ts +1 -0
- package/dist/typescript/specs/NativeEdgeToEdgeModule.d.ts.map +1 -1
- package/dist/typescript/types.d.ts +8 -5
- package/dist/typescript/types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/SystemBars.ts +27 -6
- package/src/expo.ts +33 -8
- package/src/specs/NativeEdgeToEdgeModule.ts +1 -0
- package/src/types.ts +5 -2
- package/android/src/main/res/values-v29/colors.xml +0 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# react-native-edge-to-edge
|
|
2
2
|
|
|
3
|
-
Effortlessly enable [edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge) display in React Native, allowing your Android app content to flow seamlessly beneath the system bars.
|
|
3
|
+
Effortlessly enable [edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge) display in React Native, allowing your Android (v6 and above) app content to flow seamlessly beneath the system bars.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/zoontek/react-native-edge-to-edge/blob/main/LICENSE)
|
|
6
6
|
[](https://www.npmjs.org/package/react-native-edge-to-edge)
|
|
@@ -27,16 +27,14 @@ It is supporting the **latest version**, and the **two previous minor series**.
|
|
|
27
27
|
|
|
28
28
|
Recently, Google introduced a significant change: apps targeting SDK 35 will have edge-to-edge display [enforced by default](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge) on Android 15+. 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
29
|
|
|
30
|
-
|
|
30
|
+
### Consistency
|
|
31
|
+
|
|
32
|
+
iOS has long used edge-to-edge displays, so adopting this design across all platforms ensures a consistent user experience. It also simplifies managing safe areas, eliminating the need for special cases specific to Android.
|
|
31
33
|
|
|
32
34
|
### Immersive mode
|
|
33
35
|
|
|
34
36
|
[Immersive mode](https://developer.android.com/develop/ui/views/layout/immersive) allows you to hide the status and navigation bars, making it ideal for full-screen experiences. Currently, the built-in [`StatusBar`](https://reactnative.dev/docs/statusbar) component uses [`FLAG_FULLSCREEN`](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_FULLSCREEN), a flag that has been deprecated since Android 11.
|
|
35
37
|
|
|
36
|
-
### Consistency
|
|
37
|
-
|
|
38
|
-
iOS has long used edge-to-edge displays, so adopting this design across all platforms ensures a consistent user experience. It also simplifies managing safe areas, eliminating the need for special cases specific to Android.
|
|
39
|
-
|
|
40
38
|
## Installation
|
|
41
39
|
|
|
42
40
|
```bash
|
|
@@ -45,14 +43,37 @@ $ npm i -S react-native-edge-to-edge
|
|
|
45
43
|
$ yarn add react-native-edge-to-edge
|
|
46
44
|
```
|
|
47
45
|
|
|
46
|
+
### Pick a parent theme
|
|
47
|
+
|
|
48
|
+
This library requires you to update the parent of your Android `AppTheme` to an edge-to-edge version. Don't worry, it's very easy to understand! You just need to choose a theme based on the current value:
|
|
49
|
+
|
|
50
|
+
| If you currently have… | …you should use |
|
|
51
|
+
| :---------------------------------------------- | :--------------------------------- |
|
|
52
|
+
| `Theme.AppCompat.DayNight.NoActionBar` | `Theme.EdgeToEdge` |
|
|
53
|
+
| `Theme.MaterialComponents.DayNight.NoActionBar` | `Theme.EdgeToEdge.Material2` |
|
|
54
|
+
| `Theme.Material3.DayNight.NoActionBar` | `Theme.EdgeToEdge.Material3` |
|
|
55
|
+
| `Theme.AppCompat.Light.NoActionBar` | `Theme.EdgeToEdge.Light` |
|
|
56
|
+
| `Theme.MaterialComponents.Light.NoActionBar` | `Theme.EdgeToEdge.Material2.Light` |
|
|
57
|
+
| `Theme.Material3.Light.NoActionBar` | `Theme.EdgeToEdge.Material3.Light` |
|
|
58
|
+
|
|
48
59
|
### Expo
|
|
49
60
|
|
|
50
|
-
Add the library plugin in your `app.json` config file and [create a new build](https://docs.expo.dev/develop/development-builds/create-a-build
|
|
61
|
+
Add the library plugin in your `app.json` config file and [create a new build](https://docs.expo.dev/develop/development-builds/create-a-build) 👷:
|
|
51
62
|
|
|
52
|
-
```
|
|
63
|
+
```json
|
|
53
64
|
{
|
|
54
65
|
"expo": {
|
|
55
|
-
|
|
66
|
+
"plugins": [
|
|
67
|
+
[
|
|
68
|
+
"react-native-edge-to-edge",
|
|
69
|
+
{
|
|
70
|
+
"android": {
|
|
71
|
+
"parentTheme": "Light",
|
|
72
|
+
"enforceNavigationBarContrast": false
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
]
|
|
56
77
|
}
|
|
57
78
|
}
|
|
58
79
|
```
|
|
@@ -60,10 +81,20 @@ Add the library plugin in your `app.json` config file and [create a new build](h
|
|
|
60
81
|
_📌 The available plugins options are:_
|
|
61
82
|
|
|
62
83
|
```ts
|
|
84
|
+
type ParentTheme =
|
|
85
|
+
| "Default" // uses `Theme.EdgeToEdge`
|
|
86
|
+
| "Material2" // uses `Theme.EdgeToEdge.Material2`
|
|
87
|
+
| "Material3" // uses `Theme.EdgeToEdge.Material3`
|
|
88
|
+
| "Light" // uses `Theme.EdgeToEdge.Light`
|
|
89
|
+
| "Material2.Light" // uses `Theme.EdgeToEdge.Material2.Light`
|
|
90
|
+
| "Material3.Light"; // uses `Theme.EdgeToEdge.Material3.Light`
|
|
91
|
+
|
|
63
92
|
type Options = {
|
|
64
93
|
android?: {
|
|
65
|
-
//
|
|
66
|
-
parentTheme?:
|
|
94
|
+
// see the "Pick a parent theme" section
|
|
95
|
+
parentTheme?: ParentTheme; // optional (default: `Default`)
|
|
96
|
+
// see the "Transparent navigation bar" section
|
|
97
|
+
enforceNavigationBarContrast?: boolean; // optional (default: `true`)
|
|
67
98
|
};
|
|
68
99
|
};
|
|
69
100
|
```
|
|
@@ -75,74 +106,27 @@ type Options = {
|
|
|
75
106
|
|
|
76
107
|
Edit your `android/app/src/main/res/values/styles.xml` file to inherit from one of the provided themes:
|
|
77
108
|
|
|
78
|
-
```
|
|
109
|
+
```xml
|
|
79
110
|
<resources>
|
|
80
|
-
<!--
|
|
81
|
-
|
|
82
|
-
+ <style name="AppTheme" parent="Theme.EdgeToEdge">
|
|
111
|
+
<!-- update your AppTheme parent (see the "Pick a parent theme" section) -->
|
|
112
|
+
<style name="AppTheme" parent="Theme.EdgeToEdge">
|
|
83
113
|
<!-- … -->
|
|
114
|
+
<!-- disable the contrasting background of the navigation bar (optional) -->
|
|
115
|
+
<item name="enforceNavigationBarContrast">false</item>
|
|
84
116
|
</style>
|
|
85
117
|
</resources>
|
|
86
118
|
```
|
|
87
119
|
|
|
88
120
|
## Considerations
|
|
89
121
|
|
|
90
|
-
###
|
|
91
|
-
|
|
92
|
-
Many libraries expose options that you can set to account for the transparency of status and navigation bars. For example, the [`useHideAnimation`](https://github.com/zoontek/react-native-bootsplash?tab=readme-ov-file#usehideanimation) hook in `react-native-bootsplash` has `statusBarTranslucent` and `navigationBarTranslucent` options, the [`useAnimatedKeyboard`](https://docs.swmansion.com/react-native-reanimated/docs/device/useAnimatedKeyboard) in `react-native-reanimated` has an `isStatusBarTranslucentAndroid` option, etc.
|
|
122
|
+
### Transparent navigation bar
|
|
93
123
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
For library authors, we provide a lightweight package called `react-native-is-edge-to-edge` (note the `-is-`!), which checks whether `react-native-edge-to-edge` is installed, making it easy to update your library accordingly:
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import {
|
|
101
|
-
controlEdgeToEdgeValues,
|
|
102
|
-
isEdgeToEdge,
|
|
103
|
-
} from "react-native-is-edge-to-edge";
|
|
104
|
-
|
|
105
|
-
const EDGE_TO_EDGE = isEdgeToEdge();
|
|
106
|
-
|
|
107
|
-
function MyAwesomeLibraryComponent({
|
|
108
|
-
statusBarTranslucent,
|
|
109
|
-
navigationBarTranslucent,
|
|
110
|
-
}) {
|
|
111
|
-
if (__DEV__) {
|
|
112
|
-
// warn the user once about unnecessary defined values
|
|
113
|
-
controlEdgeToEdgeValues({
|
|
114
|
-
statusBarTranslucent,
|
|
115
|
-
navigationBarTranslucent,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return (
|
|
120
|
-
<MyAwesomeLibraryNativeComponent
|
|
121
|
-
statusBarTranslucent={EDGE_TO_EDGE || statusBarTranslucent}
|
|
122
|
-
navigationBarTranslucent={EDGE_TO_EDGE || navigationBarTranslucent}
|
|
123
|
-
// …
|
|
124
|
-
/>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
If you want to check for the library's presence on the native side to bypass certain parts of your code, consider using this small utility:
|
|
130
|
-
|
|
131
|
-
```kotlin
|
|
132
|
-
object EdgeToEdge {
|
|
133
|
-
// we cannot detect edge-to-edge, but we can detect react-native-edge-to-edge install
|
|
134
|
-
val ENABLED: Boolean = try {
|
|
135
|
-
Class.forName("com.zoontek.rnedgetoedge.EdgeToEdgePackage")
|
|
136
|
-
true
|
|
137
|
-
} catch (exception: ClassNotFoundException) {
|
|
138
|
-
false
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
```
|
|
124
|
+
By default, this library adopts [Android 15 defaults](https://developer.android.com/about/versions/15/behavior-changes-15#ux): a fully transparent status bar, a fully transparent gesture navigation bar, and a semi-opaque button navigation bar. To enforce full transparency in all cases, set the `enforceNavigationBarContrast` option to `false`.<br/>
|
|
125
|
+
Note that by doing so, you will need to manage the navigation bar style (using `SystemBars`) in the same way you handle the status bar.
|
|
142
126
|
|
|
143
127
|
### Keyboard management
|
|
144
128
|
|
|
145
|
-
Enabling edge-to-edge display disrupts
|
|
129
|
+
Enabling edge-to-edge display disrupts Android keyboard management (`android:windowSoftInputMode="adjustResize"`), requiring an alternative solution. While [`KeyboardAvoidingView`](https://reactnative.dev/docs/keyboardavoidingview) is a viable option, we recommend using [react-native-keyboard-controller](https://github.com/kirillzyusko/react-native-keyboard-controller) for its enhanced capabilities.
|
|
146
130
|
|
|
147
131
|
### Safe area management
|
|
148
132
|
|
|
@@ -150,22 +134,24 @@ Effective safe area management is essential to prevent content from being displa
|
|
|
150
134
|
|
|
151
135
|
### Modal component quirks
|
|
152
136
|
|
|
153
|
-
|
|
137
|
+
Edge-to-edge support for the built-in [`Modal`](https://reactnative.dev/docs/modal) component will be available in [React Native 0.77](https://github.com/facebook/react-native/pull/47254). Meanwhile, we recommend using the [react-navigation modals](https://reactnavigation.org/docs/modal) or the [`expo-router` modal screens](https://docs.expo.dev/router/advanced/modals/#modal-screen-using-expo-router).
|
|
154
138
|
|
|
155
139
|
## API
|
|
156
140
|
|
|
157
141
|
### `<SystemBars />`
|
|
158
142
|
|
|
159
|
-
A component for managing your app's system bars.
|
|
143
|
+
A component for managing your app's system bars. Replace all occurrences of [`StatusBar`](https://reactnative.dev/docs/statusbar), [`expo-status-bar`](https://docs.expo.dev/versions/latest/sdk/status-bar) and [`expo-navigation-bar`](https://docs.expo.dev/versions/latest/sdk/navigation-bar/) with it (they uses a lot of now [deprecated APIs](https://developer.android.com/about/versions/15/behavior-changes-15#deprecated-apis) and interfere with edge-to-edge).
|
|
160
144
|
|
|
161
145
|
```tsx
|
|
162
146
|
import { SystemBars } from "react-native-edge-to-edge";
|
|
163
147
|
|
|
148
|
+
// "auto" is based on current color scheme (light -> dark content, dark -> light content)
|
|
149
|
+
type Style = "auto" | "light" | "dark";
|
|
150
|
+
|
|
164
151
|
type SystemBarsProps = {
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Hide system bars (the navigation bar cannot be hidden on iOS)
|
|
152
|
+
// set the color of the system bar content (as no effect on semi-opaque navigation bar)
|
|
153
|
+
style?: Style | { statusBar?: Style; navigationBar?: Style };
|
|
154
|
+
// hide system bars (the navigation bar cannot be hidden on iOS)
|
|
169
155
|
hidden?: boolean | { statusBar?: boolean; navigationBar?: boolean };
|
|
170
156
|
};
|
|
171
157
|
|
|
@@ -199,3 +185,19 @@ const entry: SystemBarsEntry = SystemBars.replaceStackEntry(
|
|
|
199
185
|
props /*: SystemBarsProps */,
|
|
200
186
|
);
|
|
201
187
|
```
|
|
188
|
+
|
|
189
|
+
## Third-party libraries 🧩
|
|
190
|
+
|
|
191
|
+
If you're an author and your package interferes with edge-to-edge, refer to the [`react-native-is-edge-to-edge` `README.md`](./react-native-is-edge-to-edge) for compatibility instructions.
|
|
192
|
+
|
|
193
|
+
## Troubleshooting 🤔
|
|
194
|
+
|
|
195
|
+
#### The system bars stays opaque
|
|
196
|
+
|
|
197
|
+
Until third-party libraries officially add support for `react-native-edge-to-edge` to set these options automatically, you may need to adjust them manually to prevent interference with the library.
|
|
198
|
+
|
|
199
|
+
For example, make sure to set `react-native-reanimated` `useAnimatedKeyboard` `isStatusBarTranslucentAndroid` and `isNavigationBarTranslucentAndroid` to `true` (until [this PR](https://github.com/software-mansion/react-native-reanimated/pull/6732) is merged), or to replace all occurrences of the built-in `StatusBar`, [`expo-status-bar`](https://docs.expo.dev/versions/latest/sdk/status-bar) and [`expo-navigation-bar`](https://docs.expo.dev/versions/latest/sdk/navigation-bar/) with `SystemBars`.
|
|
200
|
+
|
|
201
|
+
#### The navigation bar style is erratic
|
|
202
|
+
|
|
203
|
+
There's currently [an open issue](https://issuetracker.google.com/issues/346386744) with the Android 15 emulator image regarding the navigation bar style when it is is fully transparent. This issue does not occur on physical devices.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
package com.zoontek.rnedgetoedge
|
|
2
2
|
|
|
3
|
+
import android.os.Build.VERSION
|
|
4
|
+
import android.os.Build.VERSION_CODES
|
|
5
|
+
|
|
6
|
+
import android.app.Activity
|
|
3
7
|
import android.content.res.Configuration
|
|
4
8
|
import android.graphics.Color
|
|
5
|
-
import android.
|
|
9
|
+
import android.util.TypedValue
|
|
6
10
|
import android.view.WindowManager
|
|
7
11
|
|
|
8
|
-
import androidx.core.content.ContextCompat
|
|
9
12
|
import androidx.core.view.WindowCompat
|
|
10
13
|
import androidx.core.view.WindowInsetsCompat
|
|
11
14
|
import androidx.core.view.WindowInsetsControllerCompat
|
|
@@ -15,9 +18,28 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
15
18
|
import com.facebook.react.bridge.ReadableMap
|
|
16
19
|
import com.facebook.react.common.ReactConstants
|
|
17
20
|
|
|
21
|
+
internal val LightNavigationBarColor = Color.argb(0xe6, 0xFF, 0xFF, 0xFF)
|
|
22
|
+
internal val DarkNavigationBarColor = Color.argb(0x80, 0x1b, 0x1b, 0x1b)
|
|
23
|
+
|
|
18
24
|
object EdgeToEdgeModuleImpl {
|
|
19
25
|
const val NAME = "RNEdgeToEdge"
|
|
20
26
|
|
|
27
|
+
private val boolAttributes = mutableMapOf<Int, Boolean>()
|
|
28
|
+
|
|
29
|
+
private fun resolveBoolAttribute(activity: Activity, resId: Int): Boolean =
|
|
30
|
+
boolAttributes.getOrPut(resId) {
|
|
31
|
+
val value = TypedValue()
|
|
32
|
+
activity.theme.resolveAttribute(resId, value, true) && value.data != 0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private fun isNavigationBarLight(activity: Activity): Boolean =
|
|
36
|
+
resolveBoolAttribute(activity, R.attr.enforceNavigationBarLightTheme) ||
|
|
37
|
+
activity.window.decorView.resources.configuration.uiMode and
|
|
38
|
+
Configuration.UI_MODE_NIGHT_MASK != Configuration.UI_MODE_NIGHT_YES
|
|
39
|
+
|
|
40
|
+
private fun isNavigationBarTransparent(activity: Activity): Boolean =
|
|
41
|
+
!resolveBoolAttribute(activity, R.attr.enforceNavigationBarContrast)
|
|
42
|
+
|
|
21
43
|
@Suppress("DEPRECATION")
|
|
22
44
|
fun applyEdgeToEdge(reactContext: ReactApplicationContext) {
|
|
23
45
|
val activity = reactContext.currentActivity
|
|
@@ -26,29 +48,43 @@ object EdgeToEdgeModuleImpl {
|
|
|
26
48
|
activity.runOnUiThread {
|
|
27
49
|
val window = activity.window
|
|
28
50
|
val view = window.decorView
|
|
29
|
-
val context = view.context
|
|
30
51
|
|
|
31
52
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
32
53
|
|
|
33
54
|
window.statusBarColor = Color.TRANSPARENT
|
|
34
|
-
window.navigationBarColor = ContextCompat.getColor(context, R.color.navigationBarColor)
|
|
35
55
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Configuration.UI_MODE_NIGHT_YES
|
|
56
|
+
if (VERSION.SDK_INT >= VERSION_CODES.O_MR1 && isNavigationBarTransparent(activity)) {
|
|
57
|
+
window.navigationBarColor = Color.TRANSPARENT
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
|
|
60
|
+
window.isStatusBarContrastEnforced = false
|
|
61
|
+
window.isNavigationBarContrastEnforced = false
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
val isLight = isNavigationBarLight(activity)
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
window.navigationBarColor = when {
|
|
67
|
+
VERSION.SDK_INT >= VERSION_CODES.Q -> Color.TRANSPARENT
|
|
68
|
+
VERSION.SDK_INT >= VERSION_CODES.O_MR1 && isLight -> LightNavigationBarColor
|
|
69
|
+
else -> DarkNavigationBarColor
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
WindowInsetsControllerCompat(window, view).run {
|
|
73
|
+
isAppearanceLightNavigationBars = when {
|
|
74
|
+
VERSION.SDK_INT >= VERSION_CODES.O_MR1 -> isLight
|
|
75
|
+
else -> false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
|
|
80
|
+
window.isStatusBarContrastEnforced = false
|
|
81
|
+
window.isNavigationBarContrastEnforced = true
|
|
82
|
+
}
|
|
47
83
|
}
|
|
48
84
|
|
|
49
|
-
if (
|
|
85
|
+
if (VERSION.SDK_INT >= VERSION_CODES.P) {
|
|
50
86
|
window.attributes.layoutInDisplayCutoutMode = when {
|
|
51
|
-
|
|
87
|
+
VERSION.SDK_INT >= VERSION_CODES.R -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
|
52
88
|
else -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
|
53
89
|
}
|
|
54
90
|
}
|
|
@@ -65,6 +101,8 @@ object EdgeToEdgeModuleImpl {
|
|
|
65
101
|
config.takeIf { it.hasKey("statusBarStyle") }?.getString("statusBarStyle")
|
|
66
102
|
val navigationBarHidden =
|
|
67
103
|
config.takeIf { it.hasKey("navigationBarHidden") }?.getBoolean("navigationBarHidden")
|
|
104
|
+
val navigationBarStyle =
|
|
105
|
+
config.takeIf { it.hasKey("navigationBarStyle") }?.getString("navigationBarStyle")
|
|
68
106
|
|
|
69
107
|
activity.runOnUiThread {
|
|
70
108
|
val window = activity.window
|
|
@@ -74,6 +112,12 @@ object EdgeToEdgeModuleImpl {
|
|
|
74
112
|
insetsController.isAppearanceLightStatusBars = it == "dark"
|
|
75
113
|
}
|
|
76
114
|
|
|
115
|
+
if (VERSION.SDK_INT >= VERSION_CODES.O_MR1 && isNavigationBarTransparent(activity)) {
|
|
116
|
+
navigationBarStyle?.let {
|
|
117
|
+
insetsController.isAppearanceLightNavigationBars = it == "dark"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
77
121
|
if (statusBarHidden != null || navigationBarHidden != null) {
|
|
78
122
|
insetsController.systemBarsBehavior =
|
|
79
123
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
package com.zoontek.rnedgetoedge
|
|
2
2
|
|
|
3
|
-
import com.facebook.react.
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
4
|
import com.facebook.react.bridge.NativeModule
|
|
5
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
6
|
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
7
|
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
8
|
|
|
9
|
-
class EdgeToEdgePackage :
|
|
9
|
+
class EdgeToEdgePackage : BaseReactPackage() {
|
|
10
10
|
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
11
11
|
return when (name) {
|
|
12
12
|
EdgeToEdgeModuleImpl.NAME -> EdgeToEdgeModule(reactContext)
|
|
@@ -16,21 +16,18 @@ class EdgeToEdgePackage : TurboReactPackage() {
|
|
|
16
16
|
|
|
17
17
|
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
18
18
|
return ReactModuleInfoProvider {
|
|
19
|
-
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
20
|
-
val isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
21
|
-
|
|
22
19
|
val moduleInfo = ReactModuleInfo(
|
|
23
20
|
EdgeToEdgeModuleImpl.NAME,
|
|
24
21
|
EdgeToEdgeModuleImpl.NAME,
|
|
25
|
-
false,
|
|
26
|
-
true,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
isTurboModule
|
|
22
|
+
canOverrideExistingModule = false,
|
|
23
|
+
needsEagerInit = true,
|
|
24
|
+
isCxxModule = false,
|
|
25
|
+
isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
30
26
|
)
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
mapOf(
|
|
29
|
+
EdgeToEdgeModuleImpl.NAME to moduleInfo
|
|
30
|
+
)
|
|
34
31
|
}
|
|
35
32
|
}
|
|
36
33
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<resources>
|
|
3
|
+
<public name="enforceNavigationBarContrast" type="attr" />
|
|
4
|
+
|
|
3
5
|
<public name="Theme.EdgeToEdge" type="style" />
|
|
4
6
|
<public name="Theme.EdgeToEdge.Material2" type="style" />
|
|
5
7
|
<public name="Theme.EdgeToEdge.Material3" type="style" />
|
|
8
|
+
|
|
9
|
+
<public name="Theme.EdgeToEdge.Light" type="style" />
|
|
10
|
+
<public name="Theme.EdgeToEdge.Material2.Light" type="style" />
|
|
11
|
+
<public name="Theme.EdgeToEdge.Material3.Light" type="style" />
|
|
6
12
|
</resources>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<resources>
|
|
3
|
-
<style name="Theme.EdgeToEdge.Common" parent="Theme.AppCompat.DayNight.NoActionBar">
|
|
3
|
+
<style name="Theme.EdgeToEdge.DayNight.Common" parent="Theme.AppCompat.DayNight.NoActionBar">
|
|
4
|
+
<item name="enforceNavigationBarContrast">true</item>
|
|
5
|
+
<item name="enforceNavigationBarLightTheme">false</item>
|
|
6
|
+
|
|
4
7
|
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
5
8
|
<item name="android:fitsSystemWindows">false</item>
|
|
6
9
|
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
@@ -8,7 +11,10 @@
|
|
|
8
11
|
<item name="android:windowLightStatusBar">@bool/windowLightSystemBars</item>
|
|
9
12
|
</style>
|
|
10
13
|
|
|
11
|
-
<style name="Theme.EdgeToEdge.Material2.Common" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
|
14
|
+
<style name="Theme.EdgeToEdge.Material2.DayNight.Common" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
|
15
|
+
<item name="enforceNavigationBarContrast">true</item>
|
|
16
|
+
<item name="enforceNavigationBarLightTheme">false</item>
|
|
17
|
+
|
|
12
18
|
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
13
19
|
<item name="android:fitsSystemWindows">false</item>
|
|
14
20
|
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
@@ -16,7 +22,10 @@
|
|
|
16
22
|
<item name="android:windowLightStatusBar">@bool/windowLightSystemBars</item>
|
|
17
23
|
</style>
|
|
18
24
|
|
|
19
|
-
<style name="Theme.EdgeToEdge.Material3.Common" parent="Theme.Material3.DayNight.NoActionBar">
|
|
25
|
+
<style name="Theme.EdgeToEdge.Material3.DayNight.Common" parent="Theme.Material3.DayNight.NoActionBar">
|
|
26
|
+
<item name="enforceNavigationBarContrast">true</item>
|
|
27
|
+
<item name="enforceNavigationBarLightTheme">false</item>
|
|
28
|
+
|
|
20
29
|
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
21
30
|
<item name="android:fitsSystemWindows">false</item>
|
|
22
31
|
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
@@ -24,7 +33,44 @@
|
|
|
24
33
|
<item name="android:windowLightStatusBar">@bool/windowLightSystemBars</item>
|
|
25
34
|
</style>
|
|
26
35
|
|
|
27
|
-
<style name="Theme.EdgeToEdge" parent="Theme.
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
<style name="Theme.EdgeToEdge.Light.Common" parent="Theme.AppCompat.Light.NoActionBar">
|
|
37
|
+
<item name="enforceNavigationBarContrast">true</item>
|
|
38
|
+
<item name="enforceNavigationBarLightTheme">true</item>
|
|
39
|
+
|
|
40
|
+
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
41
|
+
<item name="android:fitsSystemWindows">false</item>
|
|
42
|
+
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
43
|
+
<item name="android:statusBarColor">@android:color/transparent</item>
|
|
44
|
+
<item name="android:windowLightStatusBar">true</item>
|
|
45
|
+
</style>
|
|
46
|
+
|
|
47
|
+
<style name="Theme.EdgeToEdge.Material2.Light.Common" parent="Theme.MaterialComponents.Light.NoActionBar">
|
|
48
|
+
<item name="enforceNavigationBarContrast">true</item>
|
|
49
|
+
<item name="enforceNavigationBarLightTheme">true</item>
|
|
50
|
+
|
|
51
|
+
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
52
|
+
<item name="android:fitsSystemWindows">false</item>
|
|
53
|
+
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
54
|
+
<item name="android:statusBarColor">@android:color/transparent</item>
|
|
55
|
+
<item name="android:windowLightStatusBar">true</item>
|
|
56
|
+
</style>
|
|
57
|
+
|
|
58
|
+
<style name="Theme.EdgeToEdge.Material3.Light.Common" parent="Theme.Material3.Light.NoActionBar">
|
|
59
|
+
<item name="enforceNavigationBarContrast">true</item>
|
|
60
|
+
<item name="enforceNavigationBarLightTheme">true</item>
|
|
61
|
+
|
|
62
|
+
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
63
|
+
<item name="android:fitsSystemWindows">false</item>
|
|
64
|
+
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
|
65
|
+
<item name="android:statusBarColor">@android:color/transparent</item>
|
|
66
|
+
<item name="android:windowLightStatusBar">true</item>
|
|
67
|
+
</style>
|
|
68
|
+
|
|
69
|
+
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.DayNight.Common" />
|
|
70
|
+
<style name="Theme.EdgeToEdge.Material2" parent="Theme.EdgeToEdge.Material2.DayNight.Common" />
|
|
71
|
+
<style name="Theme.EdgeToEdge.Material3" parent="Theme.EdgeToEdge.Material3.DayNight.Common" />
|
|
72
|
+
|
|
73
|
+
<style name="Theme.EdgeToEdge.Light" parent="Theme.EdgeToEdge.Light.Common" />
|
|
74
|
+
<style name="Theme.EdgeToEdge.Material2.Light" parent="Theme.EdgeToEdge.Material2.Light.Common" />
|
|
75
|
+
<style name="Theme.EdgeToEdge.Material3.Light" parent="Theme.EdgeToEdge.Material3.Light.Common" />
|
|
30
76
|
</resources>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<resources>
|
|
3
|
-
|
|
4
|
-
<color name="navigationBarColor">#e6ffffff</color>
|
|
3
|
+
<color name="navigationBarColor">@android:color/transparent</color>
|
|
5
4
|
</resources>
|
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<resources>
|
|
3
|
-
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.Common">
|
|
3
|
+
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.DayNight.Common">
|
|
4
4
|
<item name="android:windowLightNavigationBar">@bool/windowLightSystemBars</item>
|
|
5
5
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
6
6
|
</style>
|
|
7
7
|
|
|
8
|
-
<style name="Theme.EdgeToEdge.Material2" parent="Theme.EdgeToEdge.Material2.Common">
|
|
8
|
+
<style name="Theme.EdgeToEdge.Material2" parent="Theme.EdgeToEdge.Material2.DayNight.Common">
|
|
9
9
|
<item name="android:windowLightNavigationBar">@bool/windowLightSystemBars</item>
|
|
10
10
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
11
11
|
</style>
|
|
12
12
|
|
|
13
|
-
<style name="Theme.EdgeToEdge.Material3" parent="Theme.EdgeToEdge.Material3.Common">
|
|
13
|
+
<style name="Theme.EdgeToEdge.Material3" parent="Theme.EdgeToEdge.Material3.DayNight.Common">
|
|
14
14
|
<item name="android:windowLightNavigationBar">@bool/windowLightSystemBars</item>
|
|
15
15
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
16
16
|
</style>
|
|
17
|
+
|
|
18
|
+
<style name="Theme.EdgeToEdge.Light" parent="Theme.EdgeToEdge.Light.Common">
|
|
19
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
20
|
+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
21
|
+
</style>
|
|
22
|
+
|
|
23
|
+
<style name="Theme.EdgeToEdge.Material2.Light" parent="Theme.EdgeToEdge.Material2.Light.Common">
|
|
24
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
25
|
+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
26
|
+
</style>
|
|
27
|
+
|
|
28
|
+
<style name="Theme.EdgeToEdge.Material3.Light" parent="Theme.EdgeToEdge.Material3.Light.Common">
|
|
29
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
30
|
+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
31
|
+
</style>
|
|
17
32
|
</resources>
|
|
@@ -1,23 +1,44 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
2
|
<resources>
|
|
3
|
-
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.Common">
|
|
3
|
+
<style name="Theme.EdgeToEdge" parent="Theme.EdgeToEdge.DayNight.Common">
|
|
4
4
|
<item name="android:windowLightNavigationBar">@bool/windowLightSystemBars</item>
|
|
5
5
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
6
6
|
<item name="android:enforceStatusBarContrast">false</item>
|
|
7
|
-
<item name="android:enforceNavigationBarContrast"
|
|
7
|
+
<item name="android:enforceNavigationBarContrast">?enforceNavigationBarContrast</item>
|
|
8
8
|
</style>
|
|
9
9
|
|
|
10
|
-
<style name="Theme.EdgeToEdge.Material2" parent="Theme.EdgeToEdge.Material2.Common">
|
|
10
|
+
<style name="Theme.EdgeToEdge.Material2" parent="Theme.EdgeToEdge.Material2.DayNight.Common">
|
|
11
11
|
<item name="android:windowLightNavigationBar">@bool/windowLightSystemBars</item>
|
|
12
12
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
13
13
|
<item name="android:enforceStatusBarContrast">false</item>
|
|
14
|
-
<item name="android:enforceNavigationBarContrast"
|
|
14
|
+
<item name="android:enforceNavigationBarContrast">?enforceNavigationBarContrast</item>
|
|
15
15
|
</style>
|
|
16
16
|
|
|
17
|
-
<style name="Theme.EdgeToEdge.Material3" parent="Theme.EdgeToEdge.Material3.Common">
|
|
17
|
+
<style name="Theme.EdgeToEdge.Material3" parent="Theme.EdgeToEdge.Material3.DayNight.Common">
|
|
18
18
|
<item name="android:windowLightNavigationBar">@bool/windowLightSystemBars</item>
|
|
19
19
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
20
20
|
<item name="android:enforceStatusBarContrast">false</item>
|
|
21
|
-
<item name="android:enforceNavigationBarContrast"
|
|
21
|
+
<item name="android:enforceNavigationBarContrast">?enforceNavigationBarContrast</item>
|
|
22
|
+
</style>
|
|
23
|
+
|
|
24
|
+
<style name="Theme.EdgeToEdge.Light" parent="Theme.EdgeToEdge.Light.Common">
|
|
25
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
26
|
+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
27
|
+
<item name="android:enforceStatusBarContrast">false</item>
|
|
28
|
+
<item name="android:enforceNavigationBarContrast">?enforceNavigationBarContrast</item>
|
|
29
|
+
</style>
|
|
30
|
+
|
|
31
|
+
<style name="Theme.EdgeToEdge.Material2.Light" parent="Theme.EdgeToEdge.Material2.Light.Common">
|
|
32
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
33
|
+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
34
|
+
<item name="android:enforceStatusBarContrast">false</item>
|
|
35
|
+
<item name="android:enforceNavigationBarContrast">?enforceNavigationBarContrast</item>
|
|
36
|
+
</style>
|
|
37
|
+
|
|
38
|
+
<style name="Theme.EdgeToEdge.Material3.Light" parent="Theme.EdgeToEdge.Material3.Light.Common">
|
|
39
|
+
<item name="android:windowLightNavigationBar">true</item>
|
|
40
|
+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
41
|
+
<item name="android:enforceStatusBarContrast">false</item>
|
|
42
|
+
<item name="android:enforceNavigationBarContrast">?enforceNavigationBarContrast</item>
|
|
22
43
|
</style>
|
|
23
44
|
</resources>
|