להיכנס למצב PiP בזמנים הנכונים

האפליקציה לא אמורה להיכנס למצב "תמונה בתוך תמונה" במצבים הבאים:

  • אם הסרטון נעצר או מושהה.
  • אם אתם נמצאים בדף אחר באפליקציה ולא בנגן הווידאו.

כדי לקבוע מתי האפליקציה תעבור למצב PiP, צריך להוסיף משתנה שעוקב אחרי המצב של נגן הווידאו באמצעות mutableStateOf.

החלפת מצב בהתאם להפעלה של הסרטון

כדי להחליף את המצב בהתאם לסטטוס ההפעלה של נגן הווידאו, מוסיפים מאזין בנגן הווידאו. משנים את המצב של משתנה המצב בהתאם לשאלה אם הנגן פועל או לא:

player.addListener(object : Player.Listener {
    override fun onIsPlayingChanged(isPlaying: Boolean) {
        shouldEnterPipMode = isPlaying
    }
})

החלפת מצב בהתאם לשחרור של הנגן

כשהנגן משוחרר, מגדירים את משתנה המצב לערך false:

fun releasePlayer() {
    shouldEnterPipMode = false
}

שימוש במצב כדי להגדיר אם נכנסים למצב "תמונה בתוך תמונה" (לפני Android 12)

  1. כדי להוסיף PiP בגרסאות שקודמות ל-12, צריך להשתמש ב-DisposableEffect, ולכן צריך ליצור משתנה חדש באמצעות rememberUpdatedState ולהגדיר את newValue כמשתנה המצב. כך תבטיחו שהגרסה המעודכנת תהיה בשימוש ב-DisposableEffect.
  2. ב-lambda שמגדיר את ההתנהגות כשמופעל OnUserLeaveHintListener, מוסיפים הצהרת if עם משתנה המצב סביב הקריאה ל-enterPictureInPictureMode():

    val currentShouldEnterPipMode by rememberUpdatedState(newValue = shouldEnterPipMode)
    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 {
                if (currentShouldEnterPipMode) {
                    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")
    }

שימוש במצב כדי להגדיר אם נכנסים למצב "תמונה בתוך תמונה" (בגרסאות Android אחרי Android 12)

מעבירים את משתנה המצב אל setAutoEnterEnabled כדי שהאפליקציה תיכנס למצב PiP רק בזמן הנכון:

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

    // Add autoEnterEnabled for versions S and up
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

שימוש ב-setSourceRectHint לאנימציה חלקה

ה-API של setSourceRectHint יוצר אנימציה חלקה יותר לכניסה למצב PiP. ב-Android מגרסה 12 ואילך, הוא גם יוצר אנימציה חלקה יותר ליציאה ממצב PIP. מוסיפים את ה-API הזה ל-PiP builder כדי לציין את האזור של הפעילות שגלוי אחרי המעבר ל-PiP.

  1. צריך להוסיף את setSourceRectHint() ל-builder רק אם המצב מגדיר שהאפליקציה צריכה להיכנס למצב PiP. כך נמנע חישוב של sourceRect כשהאפליקציה לא צריכה להיכנס למצב PiP.
  2. כדי להגדיר את הערך של sourceRect, משתמשים ב-layoutCoordinates שמתקבלים מהפונקציה onGloballyPositioned ב-modifier.
  3. מפעילים את setSourceRectHint() ב-builder ומעבירים את המשתנה sourceRect.

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
    }

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

VideoPlayer(pipModifier)