ตั้งค่าแอปสำหรับ PIP

ในแท็กกิจกรรมของไฟล์ AndroidManifest.xml ให้ทำดังนี้

  1. เพิ่ม supportsPictureInPicture และตั้งค่าเป็น true เพื่อประกาศว่าคุณจะ ใช้การแสดงภาพซ้อนภาพ (PIP) ในแอป
  2. เพิ่ม configChanges และตั้งค่าเป็น orientation|screenLayout|screenSize|smallestScreenSize เพื่อระบุว่า กิจกรรมของคุณจัดการการเปลี่ยนแปลงการกำหนดค่าเลย์เอาต์ ด้วยวิธีนี้ กิจกรรมของคุณจะไม่เปิดขึ้นอีกครั้งเมื่อมีการเปลี่ยนแปลงเลย์เอาต์ในระหว่างการเปลี่ยนโหมด PIP
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

ในโค้ด Compose ให้ทำดังนี้

  1. เพิ่มส่วนขยายนี้ใน Context คุณจะต้องใช้ส่วนขยายนี้หลายครั้ง ตลอดทั้งคู่มือเพื่อเข้าถึงกิจกรรม
    internal fun Context.findActivity(): ComponentActivity {
        var context = this
        while (context is ContextWrapper) {
            if (context is ComponentActivity) return context
            context = context.baseContext
        }
        throw IllegalStateException("Picture in picture should be called in the context of an Activity")
    }

เพิ่ม PIP ในแอปที่ออกจากระบบสำหรับ Android เวอร์ชันก่อน 12

หากต้องการเพิ่ม PIP สำหรับ Android เวอร์ชันก่อน 12 ให้ใช้ addOnUserLeaveHintProvider ทำตาม ขั้นตอนต่อไปนี้เพื่อเพิ่ม PIP สำหรับ Android เวอร์ชันก่อน 12

  1. เพิ่มเกตเวอร์ชันเพื่อให้เข้าถึงโค้ดนี้ได้เฉพาะในเวอร์ชัน O ถึง R
  2. ใช้ DisposableEffect โดยมี Context เป็นคีย์
  3. ภายใน DisposableEffect ให้กำหนดลักษณะการทำงานเมื่อมีการทริกเกอร์ onUserLeaveHintProvider โดยใช้ Lambda ใน Lambda ให้เรียกใช้ enterPictureInPictureMode() ใน findActivity() แล้วส่ง PictureInPictureParams.Builder().build()
  4. เพิ่ม addOnUserLeaveHintListener โดยใช้ findActivity() และส่งใน Lambda
  5. ใน onDispose ให้เพิ่ม removeOnUserLeaveHintListener โดยใช้ findActivity() และส่งใน Lambda

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
    Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
    val context = LocalContext.current
    DisposableEffect(context) {
        val onUserLeaveBehavior = Runnable {
            context.findActivity()
                .enterPictureInPictureMode(PictureInPictureParams.Builder().build())
        }
        context.findActivity().addOnUserLeaveHintListener(
            onUserLeaveBehavior
        )
        onDispose {
            context.findActivity().removeOnUserLeaveHintListener(
                onUserLeaveBehavior
            )
        }
    }
} else {
    Log.i("PiP info", "API does not support PiP")
}

เพิ่ม PIP ในแอปที่ออกจากระบบสำหรับ Android เวอร์ชันหลัง 12

หลังจาก Android 12 จะมีการเพิ่ม PictureInPictureParams.Builder ผ่านตัวแก้ไขที่ส่งไปยังวิดีโอเพลเยอร์ของแอป

  1. สร้าง modifier แล้วเรียกใช้ onGloballyPositioned ใน modifier นั้น ระบบจะใช้พิกัดเลย์เอาต์ ในขั้นตอนถัดไป
  2. สร้างตัวแปรสำหรับ PictureInPictureParams.Builder()
  3. เพิ่มคำสั่ง if เพื่อตรวจสอบว่า SDK เป็นเวอร์ชัน S หรือใหม่กว่า หากต้องการ ให้เพิ่ม setAutoEnterEnabled ลงในเครื่องมือสร้างและตั้งค่าเป็น true เพื่อเข้าสู่โหมด PIP เมื่อปัด ซึ่งจะทำให้ภาพเคลื่อนไหวราบรื่นกว่าการใช้ enterPictureInPictureMode
  4. ใช้ findActivity() เพื่อโทรหา setPictureInPictureParams() โทรหา build() ใน builder แล้วส่งมาให้เรา

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(true)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}
VideoPlayer(pipModifier)

ใช้ setAspectRatio เพื่อตั้งค่าสัดส่วนภาพของหน้าต่าง PIP

หากต้องการตั้งค่าสัดส่วนภาพของหน้าต่าง PIP คุณสามารถเลือกสัดส่วนภาพที่เฉพาะเจาะจง หรือใช้ความกว้างและความสูงของขนาดวิดีโอของเพลเยอร์ก็ได้ หากคุณใช้เพลเยอร์ Media3 ให้ตรวจสอบว่าเพลเยอร์ไม่ใช่ Null และขนาดวิดีโอของเพลเยอร์ไม่เท่ากับ VideoSize.UNKNOWN ก่อนตั้งค่าสัดส่วน ภาพ

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
        builder.setAspectRatio(
            Rational(player.videoSize.width, player.videoSize.height)
        )
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

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