Jetpack Compose 中如何實現全面屏

SharpCJ發表於2024-04-27

看問題本質,設定全面屏,是系統視窗的行為,與 View 和 Compose 有什麼關係呢?
所以,原理和傳統 View 檢視是一樣的,甚至 Api 都是一模一樣的,不熟悉的可以看我之前的文章。傳送門:

Android 全面屏體驗

那為什麼還要寫這篇文章呢?主要是在 Compose 中寫法上的一些區別,直接上程式碼:

找到主題設定的程式碼,預設生成的主題如下:

@Composable
fun HelloComposeTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }

        darkTheme -> DarkColorScheme
        else -> LightColorScheme
    }
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = colorScheme.primary.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
        }
    }

    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography,
        content = content
    )
}

與系統狀態列,導航欄相關的程式碼:

修改如下:

val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            // window.statusBarColor = colorScheme.primary.toArgb()
            // 設定狀態列和導航欄透明
            window.statusBarColor = Color.TRANSPARENT
            window.navigationBarColor = Color.TRANSPARENT
            
            // 讓內容可以顯示到狀態列和導航欄下面區域
            WindowCompat.setDecorFitsSystemWindows(window, false)

            // light 主題顯示深色,dark 主題顯示淺色,強制顯示深色,就設為 true, 前置顯示淺色就設為 false
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme 

            // 導航欄預設會有一層半透明遮罩, 這行程式碼,去掉預設半透明遮罩
            window.isNavigationBarContrastEnforced = false
        }
    }

還剩一個問題,大多數時候,我們雖然希望內容延伸到狀態列和導航欄下面,但是並不希望內容被系統欄擋住,只是想要達到背景顏色保持一致的效果。解決思路就是頂層 View 設定了背景顏色,然後給它上下流出 padding, 其中 top padding 即為狀態列高度,bottom padding 為導航欄的高度。

傳統View檢視有兩種解決方案:

  • 動態設定。新的 api 獲取 statusBarHeight 和 navigationBarHeight,需要透過在 Activity 中註冊監聽,在回撥中獲取。這個回撥時機可能晚於一些初始化工作,所以,只能在回撥中動態設定。
  • 在 xml 檔案中,根佈局設定 fitsSystemWindows 屬性為 true

最後來說說,Compose 中如何設定呢?
Compose Modifier 中提供了一個 api —— Modifier.systemBarsPadding() 即可。

本文完。

相關文章