diff --git a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt index fa42e37d5a..cce8c34efb 100644 --- a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt +++ b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt @@ -30,16 +30,19 @@ class BottomSheetView( private lateinit var dialogRootViewGroup: DialogRootViewGroup private var eventDispatcher: EventDispatcher? = null - private val rawScreenHeight = - context.resources.displayMetrics.heightPixels - .toFloat() - private val safeScreenHeight = (rawScreenHeight - getNavigationBarHeight()).toFloat() + private val rawScreenHeight = context.resources.displayMetrics.heightPixels.toFloat() + private val safeScreenHeight = rawScreenHeight private fun getNavigationBarHeight(): Int { val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0 } + private fun getStatusBarHeight(): Int { + val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") + return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0 + } + private val onAttemptDismiss by EventDispatcher() private val onSnapPointChange by EventDispatcher() private val onStateChange by EventDispatcher() @@ -182,10 +185,37 @@ class BottomSheetView( this.destroy() } + // Configure dialog window for edge-to-edge mode + dialog.window?.apply { + // Make status bar and navigation bar transparent + setNavigationBarColor(android.graphics.Color.TRANSPARENT) + setStatusBarColor(android.graphics.Color.TRANSPARENT) + + // Set FLAG_LAYOUT_NO_LIMITS to allow layout to extend beyond system UI boundaries + // Use FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS to properly handle transparent system bars + setFlags( + android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or + android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, + android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or + android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS + ) + + // Configure system UI visibility to allow layout behind both status and navigation bars + decorView.systemUiVisibility = android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + } + val bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) bottomSheet?.let { it.setBackgroundColor(0) + it.fitsSystemWindows = false + + // Add padding to respect the status bar but not the navigation bar + val statusBarHeight = getStatusBarHeight() + it.setPadding(0, statusBarHeight, 0, 0) + val behavior = BottomSheetBehavior.from(it) behavior.state = BottomSheetBehavior.STATE_HIDDEN behavior.isFitToContents = true @@ -240,8 +270,33 @@ class BottomSheetView( val dialog = this.dialog ?: return val contentHeight = this.getContentHeight() + // Ensure edge-to-edge mode settings are maintained + dialog.window?.apply { + // Maintain transparent status and navigation bars + setNavigationBarColor(android.graphics.Color.TRANSPARENT) + setStatusBarColor(android.graphics.Color.TRANSPARENT) + + // Ensure layout flags are still set + setFlags( + android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or + android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, + android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or + android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS + ) + + // Re-apply system UI visibility settings + decorView.systemUiVisibility = android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + } + val bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) bottomSheet?.let { + it.fitsSystemWindows = false + + val statusBarHeight = getStatusBarHeight() + it.setPadding(0, statusBarHeight, 0, 0) + val behavior = BottomSheetBehavior.from(it) val currentState = behavior.state diff --git a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt index 60b9aac08c..3276a07343 100644 --- a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt +++ b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt @@ -52,6 +52,8 @@ class DialogRootViewGroup( if (ReactFeatureFlags.dispatchPointerEvents) { jSPointerDispatcher = JSPointerDispatcher(this) } + + fitsSystemWindows = false } override fun onSizeChanged( diff --git a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx index bbeab8c469..e4e37b1865 100644 --- a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx +++ b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx @@ -175,6 +175,7 @@ function BottomSheetNativeComponentInner({ Platform.OS === 'android' && { borderTopLeftRadius: cornerRadius, borderTopRightRadius: cornerRadius, + overflow: 'hidden', }, extraStyles, ]}>