จนถึง Wear OS 7 (API 37) แพลตฟอร์มไม่ได้แสดงแถบสถานะของระบบเหนือหน้าต่างแอปพลิเคชัน โดยแอปเป็นเจ้าของทั้งหน้าจอและสามารถวาดเนื้อหาใดก็ได้ที่ตำแหน่งด้านบน (12 นาฬิกา) (เช่น นาฬิกา TimeText ในแอป ส่วนหัวโค้งที่กำหนดเอง หรือตัวควบคุมด้านบน)
ตั้งแต่ Wear OS 8 เป็นต้นไป และพร้อมให้ทดสอบเวอร์ชันตัวอย่างทดลองใช้แล้วในโปรแกรมจำลอง Wear OS 7.1 เวอร์ชันตัวอย่างเบต้า (API 37.2-beta1) ระบบจะแสดงแถบสถานะเหนือหน้าต่างแอปพลิเคชันที่ตำแหน่ง 12 นาฬิกาเพื่อแสดงเวลาและสัญญาณบอกสถานะ เพื่อป้องกันไม่ให้ทับซ้อนกับแถบสถานะของระบบ แอปควรหยุดแสดงนาฬิกาของตนเอง (TimeText) และเคารพส่วนแทรกของหน้าต่างแถบสถานะด้านบน (จัดการโดยอัตโนมัติโดย AppScaffold และ ScreenScaffold จาก Wear Compose 1.8 เป็นต้นไป) หรือซ่อนแถบสถานะของระบบเมื่อต้องการประสบการณ์การใช้งานแบบเต็มหน้าจอที่สมจริง
ประโยชน์หลักๆ มีดังนี้
- ความสอดคล้องทางภาพ: ตัวอักษร การจัดวาง และเพลตด้านหลังของนาฬิกาที่สอดคล้องกันทั่วทั้งระบบและแอปทั้งหมด
- สัญญาณบอกสถานะของระบบ: อนุญาตให้แพลตฟอร์มแสดงไอคอนสถานะ (เช่น สัญญาณบอกสถานะไมโครโฟนและตำแหน่งที่ใช้งานอยู่ สถานะการเชื่อมต่อ หรือข้อมูลแบตเตอรี่) และเวลาในแพลตฟอร์มต่างๆ ระบบจะแสดงไอคอนเพียงครั้งละ 1 รายการตามลำดับความสำคัญ
- การเลื่อนและการประสานงานการเปลี่ยนอัตโนมัติ: เมื่อจับคู่กับ Jetpack Compose สำหรับ Wear OS 1.8 แถบสถานะของระบบจะซ่อนโดยอัตโนมัติเมื่อผู้ใช้เลื่อนดูเนื้อหา และจะปรากฏขึ้นอีกครั้งหลังจากไม่มีการใช้งานเป็นเวลาสั้นๆ (2 วินาที)
ตั้งค่าแอป
หากต้องการเริ่มต้นใช้งาน ให้ทำตามขั้นตอนที่จำเป็นต่อไปนี้
- ติดตั้ง Android Studio เวอร์ชันตัวอย่าง (Canary)
- ในเครื่องมือจัดการ SDK ให้ดาวน์โหลดอิมเมจระบบของโปรแกรมจำลอง Wear OS 7.1 เวอร์ชันตัวอย่าง (API 37.2-beta1) เวอร์ชันนี้ให้สิทธิ์ทดลองใช้ก่อนเปิดตัวแถบสถานะระบบ Wear OS 8 ก่อนเปิดตัว SDK ของ Wear OS 8
- ในโปรแกรมจัดการอุปกรณ์ ให้สร้างและเปิดใช้งานอุปกรณ์เสมือนจริง Wear OS โดยใช้อิมเมจ API 37.2-beta1
หากต้องการรองรับแถบสถานะของระบบในแอป ให้อัปเดตเวอร์ชัน targetSdk ของแอปเป็น 35 ขึ้นไป แพลตฟอร์มจะเปิดใช้งานแถบสถานะของระบบสำหรับแอปที่กำหนดเป้าหมายเป็น API 35 ขึ้นไปเท่านั้น เพื่อรักษาความเข้ากันได้แบบย้อนหลังสำหรับแอปเดิม
นอกจากนี้ ให้อัปเดตทรัพยากร Dependency ของ Wear Compose เป็นเวอร์ชันอัลฟ่าล่าสุด ซึ่งปัจจุบันคือ 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")
}
ใช้แถบสถานะของระบบ
ใน Wear Compose Material 3 1.8.0 เวอร์ชันอัลฟ่าล่าสุด (ปัจจุบันคือ 1.8.0-alpha02) ไลบรารีจะเลือกใช้แอปของคุณโดยอัตโนมัติด้วยการผสานพร็อพเพอร์ตี้ com.google.wear.ENABLE_GLOBAL_STATUS_BAR <meta-data> เข้ากับ AndroidManifest.xml ในระหว่างรันไทม์ AppScaffold และ ScreenScaffold จะตรวจสอบว่ามีการเปิดใช้แถบสถานะของระบบในอุปกรณ์หรือไม่ และมีการตั้งค่าพร็อพเพอร์ตี้การเลือกใช้ไฟล์ Manifest นี้เป็น 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) แทนรายการแบบเลื่อน ให้ใช้ contentPadding ที่ ScreenScaffold มีให้ในเลย์เอาต์รูทเพื่อให้องค์ประกอบ UI ด้านบนไม่ทับซ้อนกับแถบสถานะของระบบ
AppScaffold {
ScreenScaffold { contentPadding ->
Column(modifier = Modifier.padding(contentPadding)) {
Text("Static Screen Content")
}
}
}
ทำงานกับคอมโพเนนต์แบบอินเทอร์แอกทีฟเต็มหน้าจอ
คอมโพเนนต์แบบอินเทอร์แอกทีฟเต็มหน้าจอใน Wear Compose Material 3 ซึ่งรวมถึง AlertDialog, Dialog, Stepper, TimePicker และ DatePicker จะซ่อนแถบสถานะของระบบโดยอัตโนมัติขณะอยู่บนหน้าจอ เพื่อให้ตัวควบคุมมีสิทธิ์เข้าถึงด้านบนของจอแสดงผลแบบวงกลมได้อย่างเต็มที่ เมื่อปิดแล้ว แถบสถานะของระบบจะได้รับการกู้คืนโดยอัตโนมัติโดยใช้ API ตัวควบคุมส่วนแทรกของหน้าต่าง
เปลี่ยนเป็นโหมดใหญ่พิเศษ
หากต้องการเปลี่ยนไปใช้โหมดใหญ่พิเศษซึ่งจะซ่อนทั้งแถบสถานะของระบบและ TimeText ในเครื่อง ให้เพิ่ม Composable StatusBarSuppression ลงในแอปหรือหน้าจอ สงวนโหมดใหญ่พิเศษไว้สำหรับหน้าจอที่ผู้ใช้เห็นเป็นเวลาสั้นๆ (การวางซ้อนการยืนยัน กล่องโต้ตอบ) หรือหน้าจอที่ใช้ทั้งจอแสดงผล (สัญญาณบอกสถานะความคืบหน้าแบบเต็มหน้าจอ)
พิจารณาว่าควรใช้โหมดใหญ่พิเศษระดับหน้าจอเมื่อใด
หากเฉพาะหน้าจอหนึ่งๆ ในแอปควรเป็นแบบเต็มหน้าจอ/สมจริง ให้เรียกใช้ StatusBarSuppression() ภายในเนื้อหาของ ScreenScaffold
ScreenScaffold จะซ่อนแถบสถานะของระบบโดยอัตโนมัติ (และละเว้นระยะห่างจากขอบด้านในของแถบสถานะด้านบน) ขณะที่หน้าจอนั้นทำงานอยู่ จากนั้นจะคืนค่าแถบสถานะของระบบเมื่อกลับไปยังหน้าจออื่นๆ ดังนี้
AppScaffold {
ScreenScaffold() {
StatusBarSuppression()
// Full-screen immersive content
}
}
พิจารณาว่าควรใช้โหมดใหญ่พิเศษระดับแอปเมื่อใด
หากแอปพลิเคชันทั้งหมด (หรือ Activity) เป็นประสบการณ์การใช้งานแบบเต็มหน้าจอที่สมจริงในทุกหน้าจอ ให้ใช้ StatusBarSuppression ที่ระดับ AppScaffold และรวมเนื้อหาเพื่อระงับแถบสถานะของระบบในทุกหน้าจอ
// 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 Composable ที่กำหนดเองจะระงับแถบสถานะของระบบ ดังนี้
// Screen-level custom TimeText override:
ScreenScaffold(
timeText = { TimeText { timeTextCurvedText("Custom Status") } },
) {
// Content
}
// App-level opt-out using in-app TimeText:
AppScaffold(
timeText = { TimeText() },
) {
// Screens
}
ติดตั้งใช้งานโดยใช้ Views (ไม่แนะนำ)
หากแอปใช้ Android Views แทน Jetpack Compose สำหรับ Wear OS ให้เลือกใช้ AndroidManifest.xml แอปที่อิงตามมุมมองต้องเลือกใช้โดยเพิ่มแท็ก ENABLE_GLOBAL_STATUS_BAR <meta-data> ภายใน <application> อย่างชัดเจน ซึ่งต่างจากเวอร์ชันอัลฟาล่าสุดของ Wear Compose Material 3 ที่เปิดใช้แถบสถานะของระบบโดยอัตโนมัติ
<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 ให้นำ UI แบบเดิมที่ตำแหน่ง 12 นาฬิกาออกและปรับระยะห่างจากขอบด้านบน มิฉะนั้น ให้กลับไปใช้ 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
}
ซ่อนและแสดงแถบสถานะแบบเป็นโปรแกรม
แอปที่อิงตามมุมมองต้องซ่อนหรือแสดงแถบสถานะของระบบอย่างชัดเจน (เช่น เมื่อเข้าสู่มุมมองที่สมจริงแบบเต็มหน้าจอหรือประสานงานลักษณะการเลื่อนออก) โดยใช้ WindowInsetsControllerCompat ซึ่งต่างจาก ScreenScaffold ใน Compose
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 เวอร์ชันตัวอย่างเบต้า (API 37.2-beta1) ให้ตรวจสอบสิ่งต่อไปนี้
- นาฬิกาปรากฏเพียงครั้งเดียว: ตรวจสอบว่ามีเพียงเวลาในแถบสถานะของระบบที่ปรากฏที่ตำแหน่ง 12 นาฬิกา และไม่มี
TimeTextเดิมในแอปและเนื้อหาแอปซ้อนทับอยู่ - ระยะห่างจากขอบด้านบน: ตรวจสอบว่าชื่อหน้าจอ ส่วนหัว และปุ่มด้านบนปรากฏใต้แถบสถานะ
- การวางซ้อนและกล่องโต้ตอบแบบเต็มหน้าจอ: ตรวจสอบว่ากล่องโต้ตอบ เครื่องมือเลือก ตัวเลือก และกิจกรรมแบบเต็มหน้าจอที่กำหนดเองซ่อนแถบสถานะเมื่อเปิด และคืนค่าแถบสถานะเมื่อปิด