Phối hợp giao diện người dùng với thanh trạng thái hệ thống

Cho đến Wear OS 7 (API 37), nền tảng này không hiển thị thanh trạng thái hệ thống trên cửa sổ ứng dụng – ứng dụng sở hữu toàn bộ màn hình và có thể vẽ bất kỳ nội dung nào ở vị trí trên cùng (12 giờ) (chẳng hạn như đồng hồ TimeText trong ứng dụng, tiêu đề cong tuỳ chỉnh hoặc các nút điều khiển trên cùng).

Kể từ Wear OS 8 (và hiện có sẵn để thử nghiệm bản xem trước trong Trình mô phỏng bản dùng thử Wear OS 7.1 Beta (API 37.2-beta1)), hệ thống sẽ kết xuất thanh trạng thái trên cửa sổ ứng dụng ở vị trí 12 giờ để hiển thị thời gian và chỉ báo trạng thái. Để tránh chồng chéo với thanh trạng thái của hệ thống, ứng dụng nên ngừng hiển thị đồng hồ riêng (TimeText) và tuân thủ các phần lồng ghép cửa sổ thanh trạng thái trên cùng (được AppScaffold và ScreenScaffold xử lý tự động từ Wear Compose 1.8 trở đi) hoặc ẩn thanh trạng thái của hệ thống khi cần trải nghiệm toàn màn hình sống động.

Thanh trạng thái hệ thống trong Wear OS 8
Hình 1. Thanh trạng thái hệ thống trong Wear OS 8.

Các lợi ích chính bao gồm:

  • Tính nhất quán về hình ảnh: kiểu chữ, vị trí và tấm nền đồng hồ đồng nhất trên toàn hệ thống và tất cả ứng dụng.
  • Chỉ báo trạng thái hệ thống: cho phép nền tảng hiển thị các biểu tượng trạng thái (chẳng hạn như chỉ báo micrô và vị trí đang hoạt động, trạng thái kết nối hoặc thông tin về pin) và thời gian trên các giao diện. Tại mỗi thời điểm, chỉ có một biểu tượng hiển thị dựa trên mức độ ưu tiên.
  • Tự động cuộn và phối hợp chuyển đổi: khi kết hợp với Jetpack Compose cho Wear OS 1.8, thanh trạng thái hệ thống sẽ tự động ẩn khi người dùng cuộn qua nội dung và xuất hiện lại sau một khoảng thời gian ngắn (2 giây) không hoạt động.

Thiết lập ứng dụng

Để bắt đầu, hãy hoàn tất các bước tiên quyết sau:

  1. Cài đặt Bản xem trước Android Studio (Canary).
  2. Trong Trình quản lý SDK, hãy tải Hình ảnh hệ thống của trình mô phỏng Wear OS 7.1 Bản dùng trước (API 37.2-beta1) xuống. Phiên bản này cung cấp quyền tiếp cận sớm vào thanh trạng thái hệ thống của Wear OS 8 trước khi SDK Wear OS 8 ra mắt.
  3. Trong Trình quản lý thiết bị, hãy tạo và chạy một thiết bị ảo Wear OS bằng hình ảnh API 37.2-beta1.

Để hỗ trợ thanh trạng thái hệ thống trong ứng dụng, hãy cập nhật phiên bản targetSdk của ứng dụng lên 35 trở lên. Nền tảng chỉ kích hoạt thanh trạng thái hệ thống cho các ứng dụng nhắm đến API 35 trở lên để duy trì khả năng tương thích ngược cho các ứng dụng cũ. Ngoài ra, hãy cập nhật phần phụ thuộc Wear Compose lên phiên bản alpha mới nhất (hiện là 1.8.0-alpha02) như trong đoạn mã sau. Nếu ứng dụng của bạn đang dùng phiên bản Wear Compose cũ hơn, bạn có thể sử dụng kỹ năng di chuyển Wear Compose Material 3 để hỗ trợ quá trình di chuyển.

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")
}

Sử dụng thanh trạng thái hệ thống

Trong phiên bản alpha mới nhất của Wear Compose Material 3 1.8.0 (hiện là 1.8.0-alpha02), thư viện sẽ tự động chọn sử dụng cho ứng dụng của bạn bằng cách hợp nhất thuộc tính com.google.wear.ENABLE_GLOBAL_STATUS_BAR <meta-data> vào AndroidManifest.xml. Trong thời gian chạy, AppScaffold và ScreenScaffold sẽ kiểm tra xem thanh trạng thái hệ thống có được bật trên thiết bị hay không và liệu thuộc tính chọn sử dụng tệp kê khai này có được đặt thành true hay không:

  • Trên trình mô phỏng xem trước/Wear OS 8 trở lên (khi chọn sử dụng): AppScaffold sẽ chặn TimeText nội bộ để thanh trạng thái hệ thống hiển thị rõ ràng ở vị trí 12 giờ mà không bị trùng lặp. ScreenScaffold tính toán lại contentPadding để tính đến ranh giới lồng ghép của Thanh trạng thái và điều phối việc ẩn và hiện thanh trạng thái khi danh sách cuộn.
  • Trên Wear OS 7 và các thiết bị cũ hơn (hoặc khi không chọn sử dụng): AppScaffold sẽ tự động quay lại hiển thị TimeText tiêu chuẩn trong ứng dụng, duy trì khả năng tương thích ngược hoàn toàn từ một cơ sở mã duy nhất.
@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}")
                    }
                }
            }
        }
    }
}

Dưới đây là những điều sẽ xảy ra khi chạy mẫu:

  • Ở trạng thái nghỉ (đầu danh sách): thanh trạng thái hệ thống hiển thị ở vị trí 12 giờ. Tiêu đề "Hello Status Bar" nằm bên dưới vùng lồng ghép của thanh trạng thái mà không bị cắt bớt hoặc chồng chéo.
  • Cuộn xuống: khi bạn cuộn qua các mục trong danh sách, thanh trạng thái sẽ ẩn và các mục trong danh sách sẽ cuộn từ cạnh này sang cạnh kia phía sau viền trên cùng.
  • Không hoạt động: khi bạn ngừng cuộn và thả màn hình, thanh trạng thái sẽ tự động xuất hiện lại sau khoảng 2 giây.

Xử lý các tình huống và tuỳ chỉnh phổ biến

Các phần sau đây mô tả cách xử lý các tình huống phổ biến mà bạn có thể gặp phải khi làm việc với thanh trạng thái hệ thống.

Xử lý màn hình không cuộn (tĩnh)

Trên các màn hình sử dụng bố cục tĩnh (chẳng hạn như Column hoặc Box) thay vì danh sách cuộn, hãy áp dụng contentPadding do ScreenScaffold cung cấp cho bố cục gốc để các phần tử trên giao diện người dùng trên cùng không chồng chéo lên thanh trạng thái hệ thống:

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

Làm việc với các thành phần tương tác toàn màn hình

Các thành phần tương tác toàn màn hình trong Wear Compose Material 3 (bao gồm cả AlertDialog, Dialog, Stepper, TimePicker và DatePicker) sẽ tự động ẩn thanh trạng thái hệ thống khi xuất hiện trên màn hình để các thành phần điều khiển có toàn quyền truy cập vào phần trên cùng của màn hình tròn. Khi bị loại bỏ, thanh trạng thái hệ thống sẽ tự động được khôi phục bằng API bộ điều khiển lồng ghép cửa sổ.

Chuyển sang chế độ nhập vai

Để chuyển sang chế độ hiển thị tối đa (trong đó cả thanh trạng thái hệ thống và TimeText cục bộ đều bị ẩn), hãy thêm thành phần kết hợp StatusBarSuppression vào ứng dụng hoặc màn hình của bạn. Dành chế độ hiển thị tối đa cho các màn hình mà người dùng nhìn thấy trong thời gian ngắn (lớp phủ xác nhận, hộp thoại) hoặc sử dụng toàn bộ màn hình (chỉ báo tiến trình toàn màn hình).

Cân nhắc thời điểm sử dụng chế độ hiển thị tối đa ở cấp màn hình

Nếu chỉ một màn hình cụ thể trong ứng dụng của bạn cần ở chế độ toàn màn hình/chế độ hiển thị tối đa, hãy gọi StatusBarSuppression() trong nội dung của ScreenScaffold. ScreenScaffold tự động chặn thanh trạng thái hệ thống (và bỏ qua khoảng đệm lồng ghép thanh trạng thái trên cùng) trong khi màn hình đó đang hoạt động, sau đó khôi phục thanh trạng thái hệ thống khi quay lại các màn hình khác:

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

Cân nhắc thời điểm sử dụng chế độ hiển thị tối đa ở cấp ứng dụng

Nếu toàn bộ ứng dụng (hoặc Activity) của bạn là một trải nghiệm toàn màn hình sống động trên tất cả các màn hình, hãy sử dụng StatusBarSuppression ở cấp AppScaffold và gói nội dung của bạn để chặn thanh trạng thái hệ thống trên tất cả các màn hình:

// 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
        }
    }
}

Hiển thị văn bản ghi đè thời gian tuỳ chỉnh

Nếu bạn cần hiển thị tiêu đề cong tuỳ chỉnh hoặc tạm thời chọn không sử dụng thanh trạng thái hệ thống trên một màn hình cụ thể hoặc trên toàn bộ ứng dụng trong quá trình di chuyển cho Wear OS 8, thì việc truyền một thành phần kết hợp timeText tuỳ chỉnh sẽ ẩn thanh trạng thái hệ thống:

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

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

Triển khai bằng Khung hiển thị (không nên dùng)

Nếu ứng dụng của bạn dùng Khung hiển thị Android thay vì Jetpack Compose cho Wear OS, hãy chọn sử dụng AndroidManifest.xml. Không giống như bản phát hành alpha mới nhất của Wear Compose Material 3 (tự động bật thanh trạng thái hệ thống), các ứng dụng dựa trên Khung hiển thị phải chọn sử dụng một cách rõ ràng bằng cách thêm thẻ ENABLE_GLOBAL_STATUS_BAR <meta-data> bên trong <application>:

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

Theo dõi các phần lồng ghép cửa sổ trên cùng

Sử dụng ViewCompat.setOnApplyWindowInsetsListener và kiểm tra giá trị của windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()). Khi statusBarInsets.top > 0, hãy xoá giao diện người dùng 12 giờ cũ và điều chỉnh khoảng đệm trên cùng; nếu không, hãy quay lại giao diện người dùng cũ:

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
}

Ẩn và hiện thanh trạng thái theo phương thức lập trình

Không giống như ScreenScaffold trong Compose, các ứng dụng dựa trên Khung hiển thị phải ẩn hoặc hiện thanh trạng thái hệ thống một cách rõ ràng (ví dụ: khi chuyển sang chế độ xem toàn màn hình hoặc điều phối hành vi cuộn) bằng cách sử dụng 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())

Kiểm thử ứng dụng

Khi kiểm thử ứng dụng trên Trình mô phỏng bản xem trước Wear OS 7.1 Beta (API 37.2-beta1), hãy kiểm tra những điều sau:

  • Đồng hồ chỉ xuất hiện một lần: Xác minh rằng chỉ có thời gian trên thanh trạng thái hệ thống xuất hiện ở vị trí 12 giờ và không có TimeText cũ trong ứng dụng cũng như nội dung ứng dụng nào chồng chéo lên thời gian đó.
  • Khoảng đệm trên cùng: Xác minh rằng tiêu đề màn hình, tiêu đề và các nút trên cùng xuất hiện bên dưới thanh trạng thái.
  • Lớp phủ và hộp thoại toàn màn hình: Xác minh rằng hộp thoại, bộ chọn, bộ điều khiển từng bước và các hoạt động toàn màn hình tuỳ chỉnh sẽ ẩn thanh trạng thái khi mở và khôi phục thanh trạng thái khi đóng.