配合系統狀態列調整 UI

在 Wear OS 7 (API 37) 以下版本,平台不會在應用程式視窗上方顯示系統狀態列,應用程式會占滿整個螢幕,並可在頂端 (12 點鐘) 位置繪製任何內容,例如應用程式內 TimeText 時鐘、自訂曲線標頭或頂端控制項。

從 Wear OS 8 開始,系統會在應用程式視窗的 12 點鐘位置算起,顯示狀態列,用於顯示時間和狀態指標。這項功能目前可在 Wear OS 7.1 Beta 版預覽模擬器 (API 37.2-beta1) 中進行早期預先發布版測試。為避免與系統狀態列重疊,應用程式應停止算繪自己的時鐘 (TimeText),並遵循頂端狀態列視窗插邊 (Wear Compose 1.8 以上版本會由 AppScaffold 和 ScreenScaffold 自動處理),或在需要全螢幕沉浸式體驗時隱藏系統狀態列。

Wear OS 8 的系統狀態列
圖 1. Wear OS 8 的系統狀態列。

主要優點如下:

  • 視覺一致性:系統和所有應用程式的時鐘字體排版、位置和背板皆一致。
  • 系統狀態指標:允許平台在各個介面顯示狀態圖示 (例如麥克風和位置指標、連線狀態或電池資訊) 和時間。系統會根據優先順序,一次只顯示一個圖示。
  • 自動捲動和轉場協調:與 Jetpack Compose for Wear OS 1.8 搭配使用時,系統狀態列會在使用者捲動內容時自動隱藏,並在短暫閒置 (2 秒) 後重新顯示。

設定應用程式

首先,請完成下列必要步驟:

  1. 安裝 Android Studio 預先發布版 (Canary)。
  2. 在 SDK Manager 中,下載 Wear OS 7.1 預先發布版模擬器系統映像檔 (API 37.2-beta1)。這個版本可讓您在 Wear OS 8 SDK 發布前,搶先體驗 Wear OS 8 系統狀態列。
  3. 在裝置管理工具中,使用 API 37.2-beta1 映像檔建立並啟動 Wear OS 虛擬裝置。

如要在應用程式中支援系統狀態列,請將應用程式的 targetSdk 版本更新至 35 以上。平台只會為指定 API 35 以上版本的應用程式啟用系統狀態列,以保留舊版應用程式的回溯相容性。此外,請將 Wear Compose 依附元件更新至最新 Alpha 版本 (目前為 1.8.0-alpha02),如以下程式碼片段所示。如果應用程式使用舊版 Wear Compose,您可以使用 Wear Compose Material 3 遷移技能,協助遷移。

android {
    defaultConfig {
        targetSdk = 35
    }
}

dependencies {
    implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha02")
    implementation("androidx.wear.compose:compose-material3:1.8.0-alpha02")
}

使用系統狀態列

在最新 Alpha 版 Wear Compose Material 3 1.8.0 (目前為 1.8.0-alpha02) 中,程式庫會將 com.google.wear.ENABLE_GLOBAL_STATUS_BAR <meta-data> 屬性合併至 AndroidManifest.xml,自動為應用程式啟用這項功能。在執行階段,AppScaffold 和 ScreenScaffold 會檢查裝置是否啟用系統狀態列,以及這個資訊清單選擇加入屬性是否設為 true:

  • 在預先發布版模擬器/Wear OS 8 以上版本 (選擇加入時): AppScaffold 會抑制內部 TimeText,因此系統狀態列會在 12 點鐘位置乾淨顯示,不會重複。ScreenScaffold 會重新計算 contentPadding,將狀態列插邊邊界納入考量,並在清單捲動時協調隱藏和顯示狀態列。
  • 在 Wear OS 7 和舊版裝置上 (或未選擇加入時): AppScaffold 會自動改為算繪標準應用程式內 TimeText,從單一程式碼集維持完整的回溯相容性。
@Composable
fun GsbSampleApp() {
    // AppScaffold coordinates the system status bar across the app
    // and falls back to rendering TimeText on Wear OS 7 and earlier.
    AppScaffold {
        val columnState = rememberTransformingLazyColumnState()

        // ScreenScaffold includes status bar top inset clearance in
        // contentPadding and hides/shows the status bar during list scrolling.
        ScreenScaffold(scrollState = columnState) { contentPadding ->
            TransformingLazyColumn(
                state = columnState,
                contentPadding = contentPadding,
            ) {
                item {
                    ListHeader { Text("Hello Status Bar") }
                }
                items(count = 15) { index ->
                    Button(onClick = { /* Handle click */ }) {
                        Text("Item #${index + 1}")
                    }
                }
            }
        }
    }
}

執行範例時,會發生以下情況:

  • 靜止 (清單頂端):系統狀態列會顯示在 12 點鐘位置。「Hello Status Bar」標頭位於狀態列插邊區域下方,不會裁剪或重疊。
  • 向下捲動:捲動清單項目時,狀態列會隱藏,清單項目則會捲動至頂端邊框後方,呈現無邊框效果。
  • 閒置:停止捲動並放開螢幕後,狀態列會在約 2 秒後自動重新顯示。

處理常見情境和自訂設定

以下各節說明如何處理使用系統狀態列時可能遇到的常見情況。

處理非捲動 (靜態) 畫面

在採用靜態版面配置 (例如 Column 或 Box) 而非捲動清單的畫面上,請將 ScreenScaffold 提供的 contentPadding 套用至根層級版面配置,這樣頂端的 UI 元素就不會與系統狀態列重疊:

AppScaffold {
    ScreenScaffold { contentPadding ->
        Column(modifier = Modifier.padding(contentPadding)) {
            Text("Static Screen Content")
        }
    }
}

使用全螢幕互動式元件

Wear Compose Material 3 中的全螢幕互動元件 (包括 AlertDialog、Dialog、Stepper、TimePicker 和 DatePicker) 會在螢幕上自動隱藏系統狀態列,讓控制項能完整存取圓形螢幕的頂端。關閉後,系統會使用視窗插邊控制器 API 自動還原系統狀態列。

切換至沉浸模式

如要切換至沉浸模式 (系統狀態列和本機 TimeText 都會隱藏),請在應用程式或畫面中加入 StatusBarSuppression 可組合函式。沉浸模式僅適用於使用者短暫看到的畫面 (確認疊加層、對話方塊),或使用整個螢幕的畫面 (全螢幕進度指標)。

考量何時使用畫面層級沉浸模式

如果只有應用程式中的特定畫面應為全螢幕/沉浸式,請在 ScreenScaffold 的內容中呼叫 StatusBarSuppression()。ScreenScaffold 會在該畫面啟用時自動隱藏系統狀態列 (並省略頂端狀態列內嵌邊框間距),並在返回其他畫面時還原系統狀態列:

AppScaffold {
    ScreenScaffold() {
        StatusBarSuppression()
        // Full-screen immersive content
    }
}

考量何時使用應用程式層級沉浸模式

如果整個應用程式 (或 Activity) 在所有畫面上都提供沉浸式全螢幕體驗,請在 AppScaffold 層級使用 StatusBarSuppression,並包裝內容,在所有畫面上隱藏系統狀態列:

// Use StatusBarSuppression at AppScaffold level and wrap your content
// to suppress status bar in the entire scaffold.
AppScaffold {
    StatusBarSuppression {
        SwipeDismissableNavHost(...) {
            // Nested screens inherit suppression and 0.dp padding
        }
    }
}

顯示自訂時間文字覆寫

在 Wear OS 8 遷移期間,如需顯示自訂曲線標頭,或在特定畫面或整個應用程式中暫時停用系統狀態列,請傳遞自訂 timeText 可組合項,以隱藏系統狀態列:

// Screen-level custom TimeText override:
ScreenScaffold(
    timeText = { TimeText { timeTextCurvedText("Custom Status") } },
) {
    // Content
}

// App-level opt-out using in-app TimeText:
AppScaffold(
    timeText = { TimeText() },
) {
    // Screens
}

使用檢視區塊導入 (不建議)

如果應用程式使用 Android View,而非 Jetpack Compose for Wear OS,請使用 AndroidManifest.xml 選擇加入。Wear Compose Material 3 的最新 Alpha 版會自動啟用系統狀態列,但以 View 為基礎的應用程式必須在 <application> 中加入 ENABLE_GLOBAL_STATUS_BAR <meta-data> 標記,明確選擇啟用:

<application ...>
    <meta-data
        android:name="com.google.wear.ENABLE_GLOBAL_STATUS_BAR"
        android:value="true" />
</application>

監控頂端視窗插邊

使用 ViewCompat.setOnApplyWindowInsetsListener 並檢查 windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()) 的值。當 statusBarInsets.top > 0 時,請移除舊版 12 點鐘 UI 並調整頂端邊框間距;否則,請改回舊版 UI:

ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, windowInsets ->
    val statusBarInsets = windowInsets.getInsets(
        WindowInsetsCompat.Type.statusBars()
    )

    if (statusBarInsets.top > 0) {
        // status bar is visible: remove legacy 12 o'clock UI and apply top inset padding
        view.updatePadding(top = statusBarInsets.top)
    } else {
        // status bar is not visible: fall back to legacy UI and padding
    }

    WindowInsetsCompat.CONSUMED
}

以程式輔助方式隱藏及顯示狀態列

與 Compose 中的 ScreenScaffold 不同,以 View 為基礎的應用程式必須使用 WindowInsetsControllerCompat 明確隱藏或顯示系統狀態列 (例如進入全螢幕沉浸式檢視畫面或協調捲動行為時):

val insetsController = WindowCompat.getInsetsController(window, window.decorView)

// Hide the status bar
insetsController.hide(WindowInsetsCompat.Type.statusBars())

// Show the status bar
insetsController.show(WindowInsetsCompat.Type.statusBars())

測試應用程式

在 Wear OS 7.1 Beta 版預覽模擬器 (API 37.2-beta1) 上測試應用程式時,請檢查下列事項:

  • 時鐘只會顯示一次:確認只有系統狀態列時間顯示在 12 點鐘位置,且沒有舊版應用程式內 TimeText 和應用程式內容與其重疊。
  • 頂端邊框間距:確認畫面標題、標頭和頂端按鈕顯示在狀態列下方。
  • 全螢幕疊加層和對話方塊:確認對話方塊、挑選器、步進器和自訂全螢幕活動在開啟時會隱藏狀態列,並在關閉時還原狀態列。