รับรู้ถึงการพับของแอป

จอแสดงผลขนาดใหญ่ที่กางออกและสถานะการพับที่ไม่เหมือนใครช่วยให้ผู้ใช้ได้รับประสบการณ์ใหม่ๆ ในอุปกรณ์แบบพับได้ หากต้องการให้แอปของคุณรับรู้การพับใน Jetpack Compose ให้ใช้ ไลบรารี Compose Material 3 Adaptive ซึ่งมี API สำหรับฟีเจอร์หน้าต่างของอุปกรณ์แบบพับได้ เช่น การพับ บานพับ และท่าทางของอุปกรณ์ เมื่อแอปของคุณรับรู้การพับได้ แอปจะปรับเลย์เอาต์เพื่อหลีกเลี่ยงการวางเนื้อหาสําคัญในบริเวณที่พับหรือบานพับ และใช้การพับและบานพับเป็นตัวคั่นตามธรรมชาติ

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

ข้อมูลหน้าต่าง

ใน Jetpack Compose ให้ใช้collectFoldingFeaturesAsState()ฟังก์ชันคอมโพสได้ เพื่อสังเกตข้อมูลการพับหน้าต่าง collectFoldingFeaturesAsState() จะรวบรวมฟีเจอร์การพับหน้าต่างปัจจุบัน จาก WindowInfoTracker ลงใน State ของ Compose ซึ่งมีรายการออบเจ็กต์ FoldingFeature

เนื่องจาก collectFoldingFeaturesAsState() แสดงผล State ของ Compose คอมโพสได้ของคุณจะคอมโพสใหม่โดยอัตโนมัติเมื่อใดก็ตามที่สถานะการพับหรือท่าทางของอุปกรณ์ เปลี่ยนแปลง โดยไม่จำเป็นต้องมีการจัดการวงจรการทำงานหรือการรวบรวมโฟลว์ด้วยตนเอง ดังนี้

@Composable
fun FoldAwareScreen() {
    val foldingFeatures by collectFoldingFeaturesAsState()

    // Access folding features for the current window.
    val foldFeature = foldingFeatures.firstOrNull()
    if (foldFeature != null) {
        // Adapt layout based on the fold feature.
    }
}

ฟีเจอร์ของจอแสดงผลแบบพับได้

รายการองค์ประกอบ FoldingFeature ที่แสดงผลโดย collectFoldingFeaturesAsState() (ประเภทย่อยของ DisplayFeature) ให้ข้อมูลเกี่ยวกับจอแสดงผลแบบพับได้ ซึ่งรวมถึงพร็อพเพอร์ตี้ต่อไปนี้

  • state: สถานะการพับของอุปกรณ์ FLAT หรือ HALF_OPENED

  • orientation: การวางแนวของการพับหรือบานพับ HORIZONTAL หรือ VERTICAL

  • occlusionType: การพับหรือบานพับบดบังจอแสดงผลบางส่วนหรือไม่ NONE หรือ FULL

  • isSeparating: การพับหรือบานพับสร้างพื้นที่แสดงผลเชิงตรรกะ 2 พื้นที่หรือไม่ จริงหรือเท็จ

อุปกรณ์แบบพับได้ที่ HALF_OPENED จะรายงาน isSeparating เป็นจริงเสมอ เนื่องจากหน้าจอแยกออกเป็นพื้นที่แสดงผล 2 พื้นที่ นอกจากนี้ isSeparating จะเป็นจริงเสมอในอุปกรณ์แบบ 2 หน้าจอเมื่อแอปพลิเคชันครอบคลุมทั้ง 2 หน้าจอ

พร็อพเพอร์ตี้ FoldingFeature bounds (สืบทอดมาจาก DisplayFeature) แสดงถึงสี่เหลี่ยมผืนผ้าขอบเขตของฟีเจอร์การพับ เช่น การพับหรือบานพับ คุณสามารถใช้ขอบเขตเพื่อวางองค์ประกอบบนหน้าจอโดยสัมพันธ์กับฟีเจอร์ได้ ดังนี้

@Composable
fun FoldFeatureDemo() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    if (foldFeature != null) {
        val isSeparating = foldFeature.isSeparating
        val occlusionType = foldFeature.occlusionType
        val bounds = foldFeature.bounds
        // Use bounds and properties to position content.
    }
}

ท่าทางแบบวางบนโต๊ะ

แอปของคุณสามารถรองรับท่าทางต่างๆ เช่น ท่าทางแบบวางบนโต๊ะ ซึ่งโทรศัพท์วางอยู่บนพื้นผิว บานพับอยู่ในตำแหน่งแนวนอน และหน้าจอแบบพับได้กางออกครึ่งหนึ่ง โดยใช้ข้อมูลที่รวมอยู่ในออบเจ็กต์ FoldingFeature

ท่าทางแบบวางบนโต๊ะช่วยให้ผู้ใช้ใช้งานโทรศัพท์ได้สะดวกโดยไม่ต้องถือโทรศัพท์ไว้ในมือ ท่าทางแบบวางบนโต๊ะเหมาะสำหรับการดูสื่อ การถ่ายรูป และการโทรวิดีโอ

แอปวิดีโอเพลเยอร์ในท่าตั้งโต๊ะพร้อมการเล่นวิดีโอบน
        ส่วนแนวตั้งที่ตั้งตรงของหน้าจอและตัวควบคุมการเล่นบน
        ส่วนแนวนอนด้านล่าง
รูปที่ 1 แอปวิดีโอเพลเยอร์ในท่าทางแบบวางบนโต๊ะ โดยวิดีโออยู่ส่วนแนวตั้งของหน้าจอ และการควบคุมการเล่นอยู่ส่วนแนวนอน

ใช้ FoldingFeature.State และ FoldingFeature.Orientation จาก collectFoldingFeaturesAsState() เพื่อตรวจสอบว่าอุปกรณ์อยู่ในท่าทางแบบวางบนโต๊ะ หรือไม่

@Composable
fun TabletopContent() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    val isTableTopPosture = foldFeature != null &&
        foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL

    if (isTableTopPosture) {
        // Tabletop layout: separate content and controls across the fold.
    } else {
        // Standard layout.
    }
}

หรือคุณจะตรวจสอบว่าหน้าต่างอยู่ในท่าทางแบบวางบนโต๊ะหรือไม่โดย ดูพร็อพเพอร์ตี้ Posture ที่แสดงผลโดย currentWindowAdaptiveInfoV2()

val adaptiveInfo = currentWindowAdaptiveInfoV2()
val isTabletop = adaptiveInfo.windowPosture.isTabletop

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

ตัวอย่าง

ท่าทางแบบหนังสือ

อีกฟีเจอร์ที่ไม่เหมือนใครของอุปกรณ์แบบพับได้คือท่าทางแบบหนังสือ ซึ่งอุปกรณ์กางออกครึ่งหนึ่งและบานพับอยู่ในแนวตั้ง ท่าทางแบบหนังสือเหมาะสำหรับการอ่าน eBook ท่าทางแบบหนังสือจะจำลองประสบการณ์การอ่านหนังสือจริงด้วยเลย์เอาต์ 2 หน้าในอุปกรณ์แบบพับได้ที่มีหน้าจอขนาดใหญ่ซึ่งกางออกเหมือนหนังสือที่มีปก

นอกจากนี้ยังใช้สำหรับการถ่ายภาพได้หากต้องการถ่ายภาพแบบแฮนด์ฟรีด้วยอัตราส่วนภาพที่แตกต่างกัน

ใช้เทคนิคเดียวกับที่ใช้สำหรับท่าทางแบบวางบนโต๊ะเพื่อใช้ท่าทางแบบหนังสือ ตรวจสอบว่าการวางแนวของฟีเจอร์การพับเป็นแนวตั้งแทนที่จะเป็นแนวนอน

@Composable
fun BookContent() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    val isBookPosture = foldFeature != null &&
        foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.VERTICAL

    if (isBookPosture) {
        // Book posture layout: two-page layout across the vertical fold.
    } else {
        // Standard single-page layout.
    }
}

การเปลี่ยนแปลงขนาดหน้าต่าง

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

หากต้องการดึงข้อมูลคลาสขนาดหน้าต่างปัจจุบันและปรับให้เข้ากับการเปลี่ยนแปลงขนาดใน Jetpack Compose ให้ใช้ฟังก์ชันคอมโพสได้ currentWindowAdaptiveInfoV2() จาก ไลบรารี Compose Material 3 Adaptive currentWindowAdaptiveInfoV2() แสดงผลอินสแตนซ์ WindowAdaptiveInfo ซึ่งมี WindowSizeClass ของหน้าต่างปัจจุบัน (รองรับเบรกพอยต์ขนาดใหญ่และ ขนาดใหญ่พิเศษโดยค่าเริ่มต้น) รวมถึง windowPosture ของอุปกรณ์

@Composable
fun AdaptiveApp() {
    val adaptiveInfo = currentWindowAdaptiveInfoV2()
    val windowSizeClass = adaptiveInfo.windowSizeClass

    when {
        windowSizeClass.isWidthAtLeastBreakpoint(
            WIDTH_DP_EXPANDED_LOWER_BOUND
        ) -> {
            // Expanded layout
        }
        windowSizeClass.isWidthAtLeastBreakpoint(
            WIDTH_DP_MEDIUM_LOWER_BOUND
        ) -> {
            // Medium layout
        }
        else -> {
            // Compact layout
        }
    }
}

ดูหัวข้อใช้คลาสขนาดหน้าต่าง

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์ที่รับรู้การพับได้และอุปกรณ์แบบพับได้จากแหล่งข้อมูลต่อไปนี้

ตัวอย่าง

  • ตัวอย่าง Jetpack WindowManager: ตัวอย่างวิธีใช้ไลบรารี Jetpack WindowManager
  • Jetcaster : การใช้ท่าทางแบบวางบนโต๊ะกับ Compose

Codelab