From 1cf36e55490d6cc23db93795a2320f6c12dfa6c7 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 21 May 2025 17:26:31 -0500 Subject: [PATCH] Fix android system bars overlapping UI #1564 #1574 --- .../app/src/main/assets/capacitor.config.json | 4 ++ .../com/audiobookshelf/app/MainActivity.kt | 57 +++++++++++++++---- .../app/src/main/res/layout/activity_main.xml | 1 + .../app/src/main/res/values-v27/styles.xml | 11 ++++ android/app/src/main/res/values/colors.xml | 4 +- capacitor.config.json | 4 ++ ios/App/App/capacitor.config.json | 4 ++ plugins/init.client.js | 6 -- 8 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 android/app/src/main/res/values-v27/styles.xml diff --git a/android/app/src/main/assets/capacitor.config.json b/android/app/src/main/assets/capacitor.config.json index a5ef24e4..0551bb2e 100644 --- a/android/app/src/main/assets/capacitor.config.json +++ b/android/app/src/main/assets/capacitor.config.json @@ -5,6 +5,10 @@ "plugins": { "CapacitorHttp": { "enabled": false + }, + "StatusBar": { + "backgroundColor": "#232323", + "style": "DARK" } }, "server": { diff --git a/android/app/src/main/java/com/audiobookshelf/app/MainActivity.kt b/android/app/src/main/java/com/audiobookshelf/app/MainActivity.kt index 87080a82..d9726654 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/MainActivity.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/MainActivity.kt @@ -6,10 +6,15 @@ import android.content.Context import android.content.Intent import android.content.ServiceConnection import android.content.pm.PackageManager +import android.os.Build import android.os.Bundle import android.os.IBinder import android.util.Log +import android.view.ViewGroup +import android.view.WindowInsets +import android.webkit.WebView import androidx.core.app.ActivityCompat +import androidx.core.view.updateLayoutParams import com.anggrayudi.storage.SimpleStorage import com.anggrayudi.storage.SimpleStorageHelper import com.audiobookshelf.app.managers.DbManager @@ -40,18 +45,6 @@ class MainActivity : BridgeActivity() { ) public override fun onCreate(savedInstanceState: Bundle?) { - // TODO: Optimize using strict mode logs -// StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder() -// .detectDiskReads() -// .detectDiskWrites().detectAll() -// .detectNetwork() // or .detectAll() for all detectable problems -// .penaltyLog() -// .build()) -// StrictMode.setVmPolicy(VmPolicy.Builder() -// .detectLeakedSqlLiteObjects() -// .detectLeakedClosableObjects() -// .penaltyLog() -// .build()) DbManager.initialize(applicationContext) registerPlugin(AbsAudioPlayer::class.java) @@ -63,7 +56,47 @@ class MainActivity : BridgeActivity() { super.onCreate(savedInstanceState) Log.d(tag, "onCreate") + // Update the margins to handle edge-to-edge enforced in SDK 35 + // See: https://developer.android.com/develop/ui/views/layout/edge-to-edge + val webView: WebView = findViewById(R.id.webview) + webView.setOnApplyWindowInsetsListener { v, insets -> + val (left, top, right, bottom) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val sysInsets = insets.getInsets(WindowInsets.Type.systemBars()) + Log.d(tag, "safe sysInsets: $sysInsets") + arrayOf(sysInsets.left, sysInsets.top, sysInsets.right, sysInsets.bottom) + } else { + arrayOf( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom + ) + } + // Inject as CSS variables + // NOTE: Possibly able to use in the future to support edge-to-edge better. + val js = """ + document.documentElement.style.setProperty('--safe-area-inset-top', '${top}px'); + document.documentElement.style.setProperty('--safe-area-inset-bottom', '${bottom}px'); + document.documentElement.style.setProperty('--safe-area-inset-left', '${left}px'); + document.documentElement.style.setProperty('--safe-area-inset-right', '${right}px'); + """.trimIndent() + webView.evaluateJavascript(js, null) + + // Set margins + v.updateLayoutParams { + leftMargin = left + bottomMargin = bottom + rightMargin = right + topMargin = top + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + WindowInsets.CONSUMED + } else { + insets + } + } val permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) if (permission != PackageManager.PERMISSION_GRANTED) { diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index b5ad1387..aeba3591 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -7,6 +7,7 @@ tools:context=".MainActivity"> diff --git a/android/app/src/main/res/values-v27/styles.xml b/android/app/src/main/res/values-v27/styles.xml new file mode 100644 index 00000000..f20ffc86 --- /dev/null +++ b/android/app/src/main/res/values-v27/styles.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 41281939..6039c197 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -3,5 +3,5 @@ #FF81D4FA #FF039BE5 #FF01579B - #262626 - \ No newline at end of file + #232323 + diff --git a/capacitor.config.json b/capacitor.config.json index 81df5320..8947e8d7 100644 --- a/capacitor.config.json +++ b/capacitor.config.json @@ -5,6 +5,10 @@ "plugins": { "CapacitorHttp": { "enabled": false + }, + "StatusBar": { + "backgroundColor": "#232323", + "style": "DARK" } }, "server": { diff --git a/ios/App/App/capacitor.config.json b/ios/App/App/capacitor.config.json index 370d7bd3..a8d12c0a 100644 --- a/ios/App/App/capacitor.config.json +++ b/ios/App/App/capacitor.config.json @@ -5,6 +5,10 @@ "plugins": { "CapacitorHttp": { "enabled": false + }, + "StatusBar": { + "backgroundColor": "#232323", + "style": "DARK" } }, "server": { diff --git a/plugins/init.client.js b/plugins/init.client.js index fe20ad40..aa90dd4e 100644 --- a/plugins/init.client.js +++ b/plugins/init.client.js @@ -16,12 +16,6 @@ if (Capacitor.getPlatform() != 'web') { await StatusBar.setStyle({ style: Style.Dark }) } setStatusBarStyleDark() - - const setStatusBarOverlays = async () => { - // Defaults to true in capacitor v7 - await StatusBar.setOverlaysWebView({ overlay: false }) - } - setStatusBarOverlays() } Vue.prototype.$showHideStatusBar = async (show) => {