Skip to content

Commit

Permalink
Refactoring: extract helper functions from StatusBarModule (facebook#…
Browse files Browse the repository at this point in the history
…46224)

Summary:
Pull Request resolved: facebook#46224

- Extract functions from StatusBarModule so they can be reused
- WindowUtil was created as a container for the extracted Window related helper functions

Changelog: [Internal]

Differential Revision: D61834841

Reviewed By: tdn120
  • Loading branch information
alanleedev authored and facebook-github-bot committed Aug 28, 2024
1 parent 7bc9244 commit 5116c35
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 39 deletions.
5 changes: 5 additions & 0 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -8330,3 +8330,8 @@ public final class com/facebook/react/views/view/ViewGroupClickEvent : com/faceb
public fun getEventName ()Ljava/lang/String;
}

public final class com/facebook/react/views/view/WindowUtilKt {
public static final fun setStatusBarTranslucency (Landroid/view/Window;Z)V
public static final fun setStatusBarVisibility (Landroid/view/Window;Z)V
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.common.ReactConstants
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.views.view.setStatusBarTranslucency
import com.facebook.react.views.view.setStatusBarVisibility

/** [NativeModule] that allows changing the appearance of the status bar. */
@ReactModule(name = NativeStatusBarManagerAndroidSpec.NAME)
Expand Down Expand Up @@ -97,23 +99,7 @@ public class StatusBarModule(reactContext: ReactApplicationContext?) :
UiThreadUtil.runOnUiThread(
object : GuardedRunnable(reactApplicationContext) {
override fun runGuarded() {
// If the status bar is translucent hook into the window insets calculations
// and consume all the top insets so no padding will be added under the status bar.
val window = activity.window ?: return
val decorView = window.decorView
if (translucent) {
decorView.setOnApplyWindowInsetsListener { v, insets ->
val defaultInsets = v.onApplyWindowInsets(insets)
defaultInsets.replaceSystemWindowInsets(
defaultInsets.systemWindowInsetLeft,
0,
defaultInsets.systemWindowInsetRight,
defaultInsets.systemWindowInsetBottom)
}
} else {
decorView.setOnApplyWindowInsetsListener(null)
}
ViewCompat.requestApplyInsets(decorView)
activity.window?.setStatusBarTranslucency(translucent)
}
})
}
Expand All @@ -127,28 +113,7 @@ public class StatusBarModule(reactContext: ReactApplicationContext?) :
"StatusBarModule: Ignored status bar change, current activity is null.")
return
}
UiThreadUtil.runOnUiThread(
Runnable {
val window = activity.window ?: return@Runnable
if (hidden) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Ensure the content extends into the cutout area
window.attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
window.setDecorFitsSystemWindows(false)
}
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
window.setDecorFitsSystemWindows(true)
}
window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
})
UiThreadUtil.runOnUiThread { activity.window?.setStatusBarVisibility(hidden) }
}

@Suppress("DEPRECATION")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.views.view

import android.os.Build
import android.view.Window
import android.view.WindowManager
import androidx.core.view.ViewCompat

@Suppress("DEPRECATION")
public fun Window.setStatusBarTranslucency(isTranslucent: Boolean) {
// If the status bar is translucent hook into the window insets calculations
// and consume all the top insets so no padding will be added under the status bar.
if (isTranslucent) {
decorView.setOnApplyWindowInsetsListener { v, insets ->
val defaultInsets = v.onApplyWindowInsets(insets)
defaultInsets.replaceSystemWindowInsets(
defaultInsets.systemWindowInsetLeft,
0,
defaultInsets.systemWindowInsetRight,
defaultInsets.systemWindowInsetBottom)
}
} else {
decorView.setOnApplyWindowInsetsListener(null)
}
ViewCompat.requestApplyInsets(decorView)
}

public fun Window.setStatusBarVisibility(isHidden: Boolean) {
if (isHidden) {
this.statusBarHide()
} else {
this.statusBarShow()
}
}

@Suppress("DEPRECATION")
private fun Window.statusBarHide() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Ensure the content extends into the cutout area
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
setDecorFitsSystemWindows(false)
}
addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
}

@Suppress("DEPRECATION")
private fun Window.statusBarShow() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
setDecorFitsSystemWindows(true)
}
addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}

0 comments on commit 5116c35

Please sign in to comment.