คุณต้องใช้ข้อมูลหลายประเภท เช่น ความสามารถของอุปกรณ์และสถานะของแอป เพื่ออัปเดตเลย์เอาต์ของแอป ความกว้างและความสูงของหน้าต่างเป็นข้อมูลที่ใช้กันโดยทั่วไปมากที่สุด นอกจากนี้ คุณยังดูข้อมูลต่อไปนี้ได้ด้วย
- ท่าทางของหน้าต่าง
- ความแม่นยำของอุปกรณ์ชี้
- ประเภทของแป้นพิมพ์
- อุปกรณ์รองรับกล้องและไมโครโฟนหรือไม่
- ระยะห่างระหว่างผู้ใช้กับจอแสดงผลของอุปกรณ์
เนื่องจากระบบจะอัปเดตข้อมูลแบบไดนามิก คุณจึงต้องตรวจสอบข้อมูลและทริกเกอร์การจัดองค์ประกอบใหม่เมื่อมีการอัปเดต
ฟังก์ชัน mediaQuery จะสรุปรายละเอียดของการดึงข้อมูล
และช่วยให้คุณมุ่งเน้นไปที่การกำหนดเงื่อนไขเพื่อทริกเกอร์การอัปเดตเลย์เอาต์
ตัวอย่างต่อไปนี้จะเปลี่ยนเลย์เอาต์เป็น TabletopLayout เมื่อท่าทางของอุปกรณ์พับได้เป็นแบบวางบนโต๊ะ
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
เปิดใช้ฟังก์ชัน mediaQuery
หากต้องการเปิดใช้ฟังก์ชัน mediaQuery
ให้ตั้งค่าแอตทริบิวต์ isMediaQueryIntegrationEnabled ของ
ออบเจ็กต์ ComposeUiFlags เป็น true
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
กำหนดเงื่อนไขด้วยพารามิเตอร์
คุณกำหนดเงื่อนไขเป็น Lambda
ที่ประเมินภายใน UiMediaScope ได้
ฟังก์ชัน mediaQuery จะประเมินเงื่อนไขตามสถานะปัจจุบันและความสามารถของอุปกรณ์
ฟังก์ชันจะแสดงผลค่าบูลีน คุณจึงกำหนดเลย์เอาต์ด้วยกิ่งก้านแบบมีเงื่อนไข เช่น นิพจน์ if ได้
ตารางที่ 1 อธิบายพารามิเตอร์ที่ใช้ได้ใน UiMediaScope
| พารามิเตอร์ | ประเภทค่า | คำอธิบาย |
|---|---|---|
windowWidth |
Dp |
ความกว้างปัจจุบันของหน้าต่างในหน่วย dp |
windowHeight |
Dp |
ความสูงปัจจุบันของหน้าต่างในหน่วย dp |
windowPosture |
UiMediaScope.Posture |
ท่าทางปัจจุบันของหน้าต่างแอปพลิเคชัน |
pointerPrecision |
UiMediaScope.PointerPrecision |
ความแม่นยำสูงสุดของอุปกรณ์ชี้ที่ใช้ได้ |
keyboardKind |
UiMediaScope.KeyboardKind |
ประเภทของแป้นพิมพ์ที่ใช้ได้หรือเชื่อมต่ออยู่ |
hasCamera |
Boolean |
อุปกรณ์รองรับกล้องหรือไม่ |
hasMicrophone |
Boolean |
อุปกรณ์รองรับไมโครโฟนหรือไม่ |
viewingDistance |
UiMediaScope.ViewingDistance |
ระยะห่างโดยทั่วไประหว่างผู้ใช้กับหน้าจออุปกรณ์ |
ออบเจ็กต์ UiMediaScope จะแปลค่าของพารามิเตอร์
ฟังก์ชัน mediaQuery ใช้ LocalUiMediaScope.current
เพื่อเข้าถึงออบเจ็กต์ UiMediaScope
ซึ่งแสดงถึงความสามารถและบริบทปัจจุบันของอุปกรณ์
ระบบจะอัปเดตออบเจ็กต์นี้แบบไดนามิกเมื่อมีการเปลี่ยนแปลง เช่น เมื่อผู้ใช้เปลี่ยนท่าทางของอุปกรณ์
จากนั้นฟังก์ชัน mediaQuery จะประเมิน Lambda query ด้วยออบเจ็กต์ UiMediaScope ที่อัปเดตแล้วและแสดงผลค่าบูลีน
ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้จะเลือกระหว่าง TabletopLayout กับ FlatLayout โดยอิงตามค่าพารามิเตอร์ windowPosture
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
ตัดสินใจตามขนาดหน้าต่าง
Window Size Classes คือชุดเบรกพอยต์ของวิวพอร์ตที่กำหนดไว้ล่วงหน้า
ซึ่งช่วยคุณออกแบบ พัฒนา และทดสอบเลย์เอาต์แบบปรับเปลี่ยนได้
คุณสามารถเปรียบเทียบพารามิเตอร์ 2 รายการที่แสดงถึงขนาดหน้าต่างปัจจุบันกับเกณฑ์ที่กำหนดไว้ใน Window Size Classes
ตัวอย่างต่อไปนี้จะเปลี่ยนจำนวนบานหน้าต่างตามความกว้างของหน้าต่าง
คลาส WindowSizeClass มีค่าคงที่สำหรับเกณฑ์
ของ Window Size Classes (รูปที่ 1)
ฟังก์ชัน derivedMediaQuery จะประเมิน Lambda query
และรวมผลลัพธ์ไว้ใน derivedStateOf
เนื่องจาก windowWidth และ windowHeight อาจอัปเดตบ่อยครั้ง ให้เรียกฟังก์ชัน derivedMediaQuery แทนฟังก์ชัน mediaQuery เมื่ออ้างอิงพารามิเตอร์เหล่านั้นใน Lambda query
val narrowerThanMedium by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp } val narrowerThanExpanded by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp } when { narrowerThanMedium -> SinglePaneLayout() narrowerThanExpanded -> TwoPaneLayout() else -> ThreePaneLayout() }
อัปเดตเลย์เอาต์ตามท่าทางของหน้าต่าง
พารามิเตอร์ windowPosture จะอธิบายท่าทางปัจจุบันของหน้าต่างเป็นออบเจ็กต์ UiMediaScope.Posture
คุณสามารถตรวจสอบ ท่าทางปัจจุบันได้โดยเปรียบเทียบพารามิเตอร์
กับค่าที่กำหนดไว้ในคลาส UiMediaScope.Posture
ตัวอย่างต่อไปนี้จะเปลี่ยนเลย์เอาต์ตามท่าทางของหน้าต่าง
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
ตรวจสอบความแม่นยำของอุปกรณ์ชี้ที่ใช้ได้
อุปกรณ์ชี้ที่มีความแม่นยำสูงจะช่วยให้ผู้ใช้ชี้องค์ประกอบ UI ได้อย่างแม่นยำ ความแม่นยำของอุปกรณ์ชี้ขึ้นอยู่กับประเภทของอุปกรณ์
พารามิเตอร์ pointerPrecision จะอธิบายความแม่นยำของอุปกรณ์ชี้ที่ใช้ได้ เช่น เมาส์และหน้าจอสัมผัส
คลาส UiMediaScope.PointerPrecision มีค่าที่กำหนดไว้ 4 ค่า ได้แก่
Fine, Coarse, Blunt, และ None
None หมายความว่าไม่มีอุปกรณ์ชี้ที่ใช้ได้
ความแม่นยำจะเรียงจากสูงสุดไปต่ำสุดตามลำดับนี้ Fine, Coarse และ Blunt
หากมีอุปกรณ์ชี้หลายรายการที่ใช้ได้และมีความแม่นยำแตกต่างกัน ระบบจะแปลพารามิเตอร์ด้วยความแม่นยำสูงสุด
ตัวอย่างเช่น หากมีอุปกรณ์ชี้ 2 รายการ ได้แก่ อุปกรณ์ที่มีความแม่นยำ Fine และอุปกรณ์ที่มีความแม่นยำ Blunt ค่าของพารามิเตอร์ pointerPrecision จะเป็น Fine
ตัวอย่างต่อไปนี้จะแสดงปุ่มที่ใหญ่ขึ้นเมื่อผู้ใช้ใช้อุปกรณ์ชี้ที่มีความแม่นยำต่ำ
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
ตรวจสอบประเภทของแป้นพิมพ์ที่ใช้ได้
พารามิเตอร์ keyboardKind แสดงถึงประเภทของแป้นพิมพ์ที่ใช้ได้:
Physical, Virtual และ None
หากแป้นพิมพ์บนหน้าจอแสดงอยู่และมีแป้นพิมพ์ฮาร์ดแวร์ที่ใช้ได้ในเวลาเดียวกัน ระบบจะแปลพารามิเตอร์เป็น Physical
หากไม่พบแป้นพิมพ์ทั้ง 2 ประเภท ค่าของพารามิเตอร์จะเป็น None
ตัวอย่างต่อไปนี้จะแสดงข้อความแนะนำให้ผู้ใช้เชื่อมต่อแป้นพิมพ์เมื่อไม่พบแป้นพิมพ์
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
ตรวจสอบว่าอุปกรณ์รองรับกล้องและไมโครโฟนหรือไม่
อุปกรณ์บางรุ่นไม่รองรับกล้องหรือไมโครโฟน
คุณสามารถตรวจสอบว่าอุปกรณ์รองรับกล้องและไมโครโฟนหรือไม่ด้วยพารามิเตอร์ hasCamera และพารามิเตอร์ hasMicrophone
ตัวอย่างต่อไปนี้จะแสดงปุ่มที่จะใช้กับกล้องและไมโครโฟนเมื่ออุปกรณ์รองรับ
Row { OutlinedTextField(state = rememberTextFieldState()) // Show the MicButton when the device supports a microphone. if (mediaQuery { hasMicrophone }) { MicButton() } // Show the CameraButton when the device supports a camera. if (mediaQuery { hasCamera }) { CameraButton() } }
ปรับ UI ตามระยะห่างในการดูโดยประมาณ
ระยะห่างในการดูเป็นปัจจัยที่ช่วยกำหนดเลย์เอาต์
หากผู้ใช้ใช้แอปจากระยะไกล ผู้ใช้จะคาดหวังให้ข้อความและองค์ประกอบ UI มีขนาดใหญ่ขึ้น
พารามิเตอร์ viewingDistance จะแสดงระยะห่างในการดูโดยประมาณตามประเภทของอุปกรณ์และบริบทการใช้งานโดยทั่วไป
คลาส UiMediaScope.ViewingDistance มีค่าที่กำหนดไว้ 3 ค่า ได้แก่
Near, Medium และ Far
Near หมายความว่าหน้าจออยู่ใกล้ และ Far หมายความว่ามีการดูอุปกรณ์จากระยะไกล
ตัวอย่างต่อไปนี้จะเพิ่มขนาดตัวอักษรเมื่อระยะห่างในการดูเป็น Far หรือ Medium
val fontSize = when { mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp else -> 16.sp }
แสดงตัวอย่างคอมโพเนนต์ UI
คุณสามารถเรียกฟังก์ชัน mediaQuery และ derivedMediaQuery ในฟังก์ชันที่สร้างได้เพื่อแสดงตัวอย่างคอมโพเนนต์ UI
ข้อมูลโค้ดต่อไปนี้จะเลือกระหว่าง TabletopLayout กับ FlatLayout โดยอิงตามค่าพารามิเตอร์ windowPosture
หากต้องการแสดงตัวอย่าง TabletopLayout พารามิเตอร์ windowPosture ควรเป็น
UiMediaScope.Posture.Tabletop
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
ฟังก์ชัน mediaQuery และ derivedMediaQuery จะประเมิน
Lambda query ที่กำหนดไว้ภายในออบเจ็กต์ UiMediaScope
ซึ่งมีให้เป็น LocalUiMediaScope.current
คุณสามารถเขียนทับได้โดยทำตามขั้นตอนต่อไปนี้
- เปิดใช้ฟังก์ชัน
mediaQuery - กำหนดออบเจ็กต์ที่กำหนดเองซึ่งใช้ได้กับอินเทอร์เฟซ
UiMediaScope - ตั้งค่าออบเจ็กต์ที่กำหนดเองเป็น
LocalUiMediaScopeด้วยฟังก์ชันCompositionLocalProvider - เรียกฟังก์ชันที่สร้างได้เพื่อแสดงตัวอย่างใน Lambda เนื้อหาของฟังก์ชัน
CompositionLocalProvider
คุณสามารถแสดงตัวอย่าง TabletopLayout ได้ด้วยตัวอย่างต่อไปนี้
@Preview @Composable fun PreviewLayoutForTabletop() { // Step 1: Enable the mediaQuery function ComposeUiFlags.isMediaQueryIntegrationEnabled = true val currentUiMediaScope = LocalUiMediaScope.current // Step 2: Define a custom object implementing the UiMediaScope interface. // The object overrides the windowPosture parameter. // The resolution of the remaining parameters is deferred to the currentUiMediaScope object. val uiMediaScope = remember(currentUiMediaScope) { object : UiMediaScope by currentUiMediaScope { override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop } } // Step 3: Set the object to the LocalUiMediaScope. CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) { // Step 4: Call the composable to preview. when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() } } }