refactor: use safe insets from native for Android, closes #1793 and closes #1886 (#1897)

This commit is contained in:
Huang Xin 2025-08-25 15:38:49 +08:00 committed by GitHub
parent 0b01132d88
commit 5ee860f1e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 282 additions and 64 deletions

View file

@ -198,6 +198,7 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
@Suppress("DEPRECATION")
window.setDecorFitsSystemWindows(false)
val controller = window.insetsController
if (controller != null) {
@ -228,7 +229,7 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val compatController = WindowCompat.getInsetsController(window, decorView)
compatController?.let {
compatController.let {
it.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
if (!isDarkMode) {
it.isAppearanceLightStatusBars = true
@ -259,7 +260,9 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
}
}.reduce { acc, flag -> acc or flag }
}
@Suppress("DEPRECATION")
window.statusBarColor = Color.TRANSPARENT
@Suppress("DEPRECATION")
window.navigationBarColor = Color.TRANSPARENT
ret.put("success", true)
} catch (e: Exception) {
@ -366,4 +369,59 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
}
invoke.resolve()
}
private fun getStatusBarHeightInternal(): Int {
val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android")
return if (resourceId > 0) activity.resources.getDimensionPixelSize(resourceId) else 0
}
private fun getNavigationBarHeight(): Int {
val resourceId = activity.resources.getIdentifier("navigation_bar_height", "dimen", "android")
return if (resourceId > 0) activity.resources.getDimensionPixelSize(resourceId) else 0
}
private fun hasNavigationBar(): Boolean {
val resourceId = activity.resources.getIdentifier("config_showNavigationBar", "bool", "android")
return if (resourceId > 0) {
activity.resources.getBoolean(resourceId)
} else {
!android.view.ViewConfiguration.get(activity).hasPermanentMenuKey()
}
}
@Command
fun get_safe_area_insets(invoke: Invoke) {
val ret = JSObject()
try {
val rootView = activity.findViewById<View>(android.R.id.content)
val windowInsets = androidx.core.view.ViewCompat.getRootWindowInsets(rootView)
if (windowInsets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val insets = windowInsets.getInsets(
WindowInsetsCompat.Type.systemBars() or
WindowInsetsCompat.Type.displayCutout()
)
val density = activity.resources.displayMetrics.density
ret.put("top", insets.top / density)
ret.put("right", insets.right / density)
ret.put("bottom", insets.bottom / density)
ret.put("left", insets.left / density)
} else {
val statusBarHeight = getStatusBarHeightInternal()
val navBarHeight = getNavigationBarHeight()
val density = activity.resources.displayMetrics.density
ret.put("top", statusBarHeight / density)
ret.put("right", 0)
ret.put("bottom", if (hasNavigationBar()) navBarHeight / density else 0)
ret.put("left", 0)
}
} catch (e: Exception) {
ret.put("error", e.message)
ret.put("top", 0)
ret.put("right", 0)
ret.put("bottom", 0)
ret.put("left", 0)
}
invoke.resolve(ret)
}
}