Skip to content

Commit a792dad

Browse files
authored
feat: handle edge-to-edge on Android (#101)
* feat: handle edge-to-edge on Android * fix: handle custom background color in edge-to-edge * feat: detect using react-native-edge-to-edge * fix: refactor detection * docs: document edge-to-edge
1 parent 6e0d745 commit a792dad

File tree

8 files changed

+50
-8
lines changed

8 files changed

+50
-8
lines changed

android/src/main/java/com/rcttabview/RCTTabView.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
183183
val colorDrawable = ColorDrawable(backgroundColor)
184184

185185
itemBackground = colorDrawable
186+
backgroundTintList = ColorStateList.valueOf(backgroundColor)
186187
}
187188

188189
fun setActiveTintColor(color: Int?) {

android/src/main/java/com/rcttabview/RCTTabViewImpl.kt

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.rcttabview
22

33
import android.content.res.ColorStateList
4+
import android.graphics.Color
5+
import androidx.core.view.ViewCompat
6+
import androidx.core.view.WindowInsetsCompat
7+
import com.facebook.react.bridge.ReactContext
48
import com.facebook.react.bridge.ReadableArray
59
import com.facebook.react.common.MapBuilder
610

@@ -16,10 +20,6 @@ class RCTTabViewImpl {
1620
return NAME
1721
}
1822

19-
companion object {
20-
const val NAME = "RNCTabView"
21-
}
22-
2323
fun setItems(view: ReactBottomNavigationView, items: ReadableArray) {
2424
val itemsArray = mutableListOf<TabInfo>()
2525
for (i in 0 until items.size()) {
@@ -85,4 +85,29 @@ class RCTTabViewImpl {
8585
MapBuilder.of("registrationName", "onTabLongPress")
8686
)
8787
}
88+
89+
companion object {
90+
const val NAME = "RNCTabView"
91+
92+
// Detect `react-native-edge-to-edge` (https://github.com/zoontek/react-native-edge-to-edge)
93+
private val EDGE_TO_EDGE = try {
94+
Class.forName("com.zoontek.rnedgetoedge.EdgeToEdgePackage")
95+
true
96+
} catch (exception: ClassNotFoundException) {
97+
false
98+
}
99+
100+
fun getNavigationBarInset(context: ReactContext): Int {
101+
val window = context.currentActivity?.window
102+
103+
val isSystemBarTransparent = EDGE_TO_EDGE || window?.navigationBarColor == Color.TRANSPARENT
104+
105+
if (!isSystemBarTransparent) {
106+
return 0
107+
}
108+
109+
val windowInsets = ViewCompat.getRootWindowInsets(window?.decorView ?: return 0)
110+
return windowInsets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom ?: 0
111+
}
112+
}
88113
}

android/src/newarch/RCTTabViewManager.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,11 @@ class RCTTabViewManager(context: ReactApplicationContext) :
113113
val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
114114
view.measure(measureSpec, measureSpec)
115115

116+
val bottomInset = RCTTabViewImpl.getNavigationBarInset(contextInner)
117+
116118
return YogaMeasureOutput.make(
117119
toDIPFromPixel(view.measuredWidth.toFloat()),
118-
toDIPFromPixel(view.measuredHeight.toFloat())
120+
toDIPFromPixel(view.measuredHeight.toFloat() + bottomInset)
119121
)
120122
}
121123

android/src/oldarch/RCTTabViewManager.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,13 @@ class RCTTabViewManager(context: ReactApplicationContext) : SimpleViewManager<Re
133133
if (mMeasured) {
134134
return YogaMeasureOutput.make(mWidth, mHeight)
135135
}
136-
137136
val tabView = ReactBottomNavigationView(themedContext)
138137
val spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
138+
139+
val navigationBarInset = RCTTabViewImpl.getNavigationBarInset(themedContext)
139140
tabView.measure(spec, spec)
140141
this.mWidth = tabView.measuredWidth
141-
this.mHeight = tabView.measuredHeight
142+
this.mHeight = tabView.measuredHeight + navigationBarInset
142143
this.mMeasured = true
143144

144145
return YogaMeasureOutput.make(mWidth, mHeight)

docs/docs/docs/guides/_meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
["usage-with-react-navigation", "usage-with-expo-router", "usage-with-one", "standalone-usage", "android-native-styling", "handling-scrollview-insets", "usage-with-vector-icons"]
1+
["usage-with-react-navigation", "usage-with-expo-router", "usage-with-one", "standalone-usage", {"type": "divider"}, "handling-scrollview-insets", "usage-with-vector-icons", {"type": "divider"}, "android-native-styling", "edge-to-edge-support"]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Android Edge to Edge Support
2+
3+
React Native Bottom Tabs supports edge-to-edge navigation on Android.
4+
5+
In order to enable edge-to-edge follow installation instructions for [react-native-edge-to-edge](https://github.com/zoontek/react-native-edge-to-edge).
6+
7+
Once this package is installed, this library will automatically use it to enable edge-to-edge navigation on Android.
8+
9+
### Before
10+
11+
| Before | After |
12+
|:---:|:---:|
13+
| ![Before](../../public/img/no-edge-to-edge.png) | ![After](../../public/img/edge-to-edge.png) |

docs/docs/public/img/edge-to-edge.png

367 KB
Loading
369 KB
Loading

0 commit comments

Comments
 (0)