ค้นหาข้อมูลสำหรับเลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่ด้วย mediaQuery

คุณต้องมีข้อมูลหลายประเภท เช่น ความสามารถของอุปกรณ์ และสถานะของแอป เพื่ออัปเดตเลย์เอาต์ของแอป ความกว้างและความสูงของหน้าต่างเป็นข้อมูลที่ใช้กันโดยทั่วไปมากที่สุด นอกจากนี้ คุณยังดูข้อมูลต่อไปนี้ได้ด้วย

  • ท่าทางของหน้าต่าง
  • ความแม่นยำของอุปกรณ์ชี้ตำแหน่ง
  • ประเภทของแป้นพิมพ์
  • อุปกรณ์รองรับกล้องและไมโครโฟนหรือไม่
  • ระยะห่างระหว่างผู้ใช้กับจอแสดงผลของอุปกรณ์

เนื่องจากข้อมูลจะอัปเดตแบบไดนามิก คุณจึงต้องตรวจสอบและทริกเกอร์การจัดองค์ประกอบใหม่เมื่อมีการอัปเดต ฟังก์ชัน 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 จะประเมินqueryแลมบ์ดา ด้วยออบเจ็กต์ UiMediaScope ที่อัปเดตแล้ว และแสดงผลค่าบูลีน ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้จะเลือกระหว่าง TabletopLayout กับ FlatLayout โดยอิงตามค่าพารามิเตอร์ windowPosture

@Composable
fun VideoPlayer(
    // ...
) {
    // ...
            if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
                TabletopLayout()
            } else {
                FlatLayout()
            }
    // ...
}

ตัดสินใจตามขนาดหน้าต่าง

คลาสขนาดหน้าต่างคือชุดเบรกพอยต์ของวิวพอร์ตที่กำหนดไว้ ซึ่งช่วยคุณออกแบบ พัฒนา และทดสอบเลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่โฆษณา คุณสามารถเปรียบเทียบพารามิเตอร์ 2 รายการที่แสดงขนาดหน้าต่างปัจจุบัน กับเกณฑ์ที่กำหนดไว้ในคลาสขนาดหน้าต่าง ตัวอย่างต่อไปนี้จะเปลี่ยนจำนวนบานหน้าต่างตามความกว้างของหน้าต่าง คลาส WindowSizeClass มีค่าคงที่สำหรับเกณฑ์ ของคลาสขนาดหน้าต่าง (รูปที่ 1)

ฟังก์ชัน derivedMediaQuery จะประเมินแลมบ์ดา 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()
}

รูปที่ 1 เลย์เอาต์จะอัปเดตตามความกว้างของหน้าต่าง

อัปเดตเลย์เอาต์ตามท่าทางของหน้าต่าง

พารามิเตอร์ 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 อุปกรณ์ที่มีความแม่นยำ Fine จะเป็นค่าของพารามิเตอร์ pointerPrecision

ตัวอย่างต่อไปนี้แสดงปุ่มที่ใหญ่ขึ้น เมื่อผู้ใช้ใช้อุปกรณ์ชี้ที่มีความแม่นยำต่ำ

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 พารามิเตอร์ TabletopLayout ควรเป็น UiMediaScope.Posture.TabletopwindowPosture

when {
    mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout()
}

ฟังก์ชัน mediaQuery และ derivedMediaQuery จะประเมิน แลมบ์ดา query ที่ระบุภายในออบเจ็กต์ UiMediaScope ซึ่งระบุเป็น LocalUiMediaScope.current คุณลบล้างได้โดยทำตามขั้นตอนต่อไปนี้

  1. เปิดใช้ฟังก์ชัน mediaQuery
  2. กำหนดออบเจ็กต์ที่กำหนดเองซึ่งใช้ UiMediaScope อินเทอร์เฟซ
  3. ตั้งค่าออบเจ็กต์ที่กำหนดเองเป็น LocalUiMediaScope ด้วยฟังก์ชัน CompositionLocalProvider
  4. เรียกใช้ Composable เพื่อแสดงตัวอย่างใน 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()
        }
    }
}