Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,10 @@ open class CustomToolbar(
// 3. edge-to-edge with translucent navigation buttons bar.
//
// Additionally we need to gracefully handle possible display cutouts.

// We use rootWindowInsets in lieu of insets or unhandledInsets here,
// because cutout sometimes (only in certain scenarios, e.g. with headerLeft view present)
// happen to be Insets.ZERO and is not reliable.
val rootWindowInsets = rootWindowInsets
val cutoutInsets =
resolveInsetsOrZero(WindowInsetsCompat.Type.displayCutout(), rootWindowInsets)
resolveInsetsOrZero(WindowInsetsCompat.Type.displayCutout(), unhandledInsets)
val systemBarInsets =
resolveInsetsOrZero(WindowInsetsCompat.Type.systemBars(), rootWindowInsets)
val statusBarInsetsStable =
resolveInsetsOrZero(
WindowInsetsCompat.Type.systemBars(),
rootWindowInsets,
ignoreVisibility = true,
)
resolveInsetsOrZero(WindowInsetsCompat.Type.systemBars(), unhandledInsets)

// This seems to work fine in all tested configurations, because cutout & system bars overlap
// only in portrait mode & top inset is controlled separately, therefore we don't count
Expand All @@ -124,7 +113,7 @@ open class CustomToolbar(
val verticalInsets =
InsetsCompat.of(
0,
max(cutoutInsets.top, if (shouldApplyTopInset) statusBarInsetsStable.top else 0),
max(cutoutInsets.top, if (shouldApplyTopInset) systemBarInsets.top else 0),
0,
max(cutoutInsets.bottom, 0),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package com.swmansion.rnscreens.safearea

import android.annotation.SuppressLint
import android.os.Build
import android.util.Log
import android.view.View
import android.view.ViewTreeObserver
Expand Down Expand Up @@ -114,28 +115,41 @@ class SafeAreaView(
}
}

return WindowInsetsCompat
var shouldConsumeDisplayCutout = false
var consumedInsets = WindowInsetsCompat
.Builder(insets)
.apply {
if (insetType.containsSystem()) {
val consumedSystemBarsInsets = getConsumedInsetsFromSelectedEdges(
insets.getInsets(
WindowInsetsCompat.Type.systemBars(),
))

val consumedDisplayCutoutInsets = getConsumedInsetsFromSelectedEdges(
insets.getInsets(
WindowInsetsCompat.Type.displayCutout()
)
)
shouldConsumeDisplayCutout = consumedDisplayCutoutInsets == Insets.NONE

setInsets(
WindowInsetsCompat.Type.systemBars(),
getConsumedInsetsFromSelectedEdges(
insets.getInsets(
WindowInsetsCompat.Type.systemBars(),
),
),
consumedSystemBarsInsets
)
setInsets(
WindowInsetsCompat.Type.displayCutout(),
getConsumedInsetsFromSelectedEdges(
insets.getInsets(
WindowInsetsCompat.Type.displayCutout(),
),
),
consumedDisplayCutoutInsets
)
}
}.build()

// On Android versions prior to R, setInsets(WindowInsetsCompat.Type.displayCutout(), ...)
// does not work. We need to use previous API.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R && shouldConsumeDisplayCutout) {
consumedInsets = consumedInsets.consumeDisplayCutout()
}

return consumedInsets
}

private fun updateInsetsIfNeeded(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ internal fun View.resolveInsetsOrZero(
return InsetsCompat.NONE
}

val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(sourceWindowInsets, this)
// We don't use root view-aware WindowInsetsCompat to make sure we get information about display
// cutout inset being consumed by one of the ancestor views. Refer to WindowInsetsCompat
// `Impl20` implementation of getInsetsForType (case Type.DISPLAY_CUTOUT).
val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(sourceWindowInsets)
return if (!ignoreVisibility) {
windowInsetsCompat.getInsets(insetType)
} else {
Expand Down
Loading