Stay organized with collections
Save and categorize content based on your preferences.
Your app should not enter PiP mode in the following situations:
If the video is stopped or paused.
If you are on a different page of the app than the video player.
To control when your app enters PiP mode, add a variable that tracks the state
of the video player using a mutableStateOf.
Toggle state based on if video is playing
To toggle the state based on if the video player is playing, add a listener on
the video player. Toggle the state of your state variable based on if the player
is playing or not:
Use state to define if PiP mode is entered (pre-Android 12)
Since adding PiP pre-12 uses a DisposableEffect, you need to create
a new variable by rememberUpdatedState with newValue set as your
state variable. This will ensure that the updated version is used within the
DisposableEffect.
In the lambda that defines the behavior when the OnUserLeaveHintListener
is triggered, add an if statement with the state variable around the call to
enterPictureInPictureMode():
valcurrentShouldEnterPipModebyrememberUpdatedState(newValue=shouldEnterPipMode)if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O&&
Build.VERSION.SDK_INT < Build.VERSION_CODES.S){valcontext=LocalContext.currentDisposableEffect(context){valonUserLeaveBehavior:()->Unit={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")}
Use state to define if PiP mode is entered (post-Android 12)
Pass your state variable into setAutoEnterEnabled so that your app only enters
PiP mode at the right time:
valpipModifier=modifier.onGloballyPositioned{layoutCoordinates->
valbuilder=PictureInPictureParams.Builder()// Add autoEnterEnabled for versions S and upif(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S){builder.setAutoEnterEnabled(shouldEnterPipMode)}context.findActivity().setPictureInPictureParams(builder.build())}VideoPlayer(pipModifier)
Use setSourceRectHint to implement a smooth animation
The setSourceRectHint API creates a smoother animation for entering PiP
mode. In Android 12+, it also creates a smoother animation for exiting PiP mode.
Add this API to the PiP builder to indicate the area of the activity that is
visible following the transition into PiP.
Only add setSourceRectHint() to the builder if the state defines that the
app should enter PiP mode. This avoids calculating sourceRect when the app
does not need to enter PiP.
To set the sourceRect value, use the layoutCoordinates that are given
from the onGloballyPositioned function on the modifier.
Call setSourceRectHint() on the builder and pass in the sourceRect
variable.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-05-20 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-05-20 UTC."],[],[],null,["# Enter PiP at correct times\n\nYour app should not enter PiP mode in the following situations:\n\n- If the video is stopped or paused.\n- If you are on a different page of the app than the video player.\n\nTo control when your app enters PiP mode, add a variable that tracks the state\nof the video player using a [`mutableStateOf`](/reference/kotlin/androidx/compose/runtime/package-summary#mutableStateOf(kotlin.Any,androidx.compose.runtime.SnapshotMutationPolicy)).\n\nToggle state based on if video is playing\n-----------------------------------------\n\nTo toggle the state based on if the video player is playing, add a listener on\nthe video player. Toggle the state of your state variable based on if the player\nis playing or not:\n\n\n```kotlin\nplayer.addListener(object : Player.Listener {\n override fun onIsPlayingChanged(isPlaying: Boolean) {\n shouldEnterPipMode = isPlaying\n }\n})https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L171-L175\n```\n\n\u003cbr /\u003e\n\nToggle state based on if player is released\n-------------------------------------------\n\nWhen the player is released, set your state variable to `false`:\n\n\n```kotlin\nfun releasePlayer() {\n shouldEnterPipMode = false\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L180-L182\n```\n\n\u003cbr /\u003e\n\nUse state to define if PiP mode is entered (pre-Android 12)\n-----------------------------------------------------------\n\n1. Since adding PiP pre-12 uses a [`DisposableEffect`](/develop/ui/compose/side-effects#disposableeffect), you need to create a new variable by [`rememberUpdatedState`](/develop/ui/compose/side-effects#rememberupdatedstate) with `newValue` set as your state variable. This will ensure that the updated version is used within the `DisposableEffect`.\n2. In the lambda that defines the behavior when the `OnUserLeaveHintListener`\n is triggered, add an `if` statement with the state variable around the call to\n `enterPictureInPictureMode()`:\n\n\n ```kotlin\n val currentShouldEnterPipMode by rememberUpdatedState(newValue = shouldEnterPipMode)\n if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.O &&\n Build.VERSION.SDK_INT \u003c Build.VERSION_CODES.S\n ) {\n val context = LocalContext.current\n DisposableEffect(context) {\n val onUserLeaveBehavior: () -\u003e Unit = {\n if (currentShouldEnterPipMode) {\n context.findActivity()\n .enterPictureInPictureMode(PictureInPictureParams.Builder().build())\n }\n }\n context.findActivity().addOnUserLeaveHintListener(\n onUserLeaveBehavior\n )\n onDispose {\n context.findActivity().removeOnUserLeaveHintListener(\n onUserLeaveBehavior\n )\n }\n }\n } else {\n Log.i(\"PiP info\", \"API does not support PiP\")\n }https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L381-L404\n ```\n\n \u003cbr /\u003e\n\nUse state to define if PiP mode is entered (post-Android 12)\n------------------------------------------------------------\n\nPass your state variable into `setAutoEnterEnabled` so that your app only enters\nPiP mode at the right time:\n\n\n```kotlin\nval pipModifier = modifier.onGloballyPositioned { layoutCoordinates -\u003e\n val builder = PictureInPictureParams.Builder()\n\n // Add autoEnterEnabled for versions S and up\n if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.S) {\n builder.setAutoEnterEnabled(shouldEnterPipMode)\n }\n context.findActivity().setPictureInPictureParams(builder.build())\n}\n\nVideoPlayer(pipModifier)https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L194-L204\n```\n\n\u003cbr /\u003e\n\nUse `setSourceRectHint` to implement a smooth animation\n-------------------------------------------------------\n\nThe [`setSourceRectHint`](/reference/android/app/PictureInPictureParams.Builder#setSourceRectHint(android.graphics.Rect)) API creates a smoother animation for entering PiP\nmode. In Android 12+, it also creates a smoother animation for exiting PiP mode.\nAdd this API to the PiP builder to indicate the area of the activity that is\nvisible following the transition into PiP.\n\n1. Only add `setSourceRectHint()` to the `builder` if the state defines that the app should enter PiP mode. This avoids calculating `sourceRect` when the app does not need to enter PiP.\n2. To set the `sourceRect` value, use the `layoutCoordinates` that are given from the [`onGloballyPositioned`](/reference/kotlin/androidx/compose/ui/layout/OnGloballyPositionedModifier) function on the modifier.\n3. Call `setSourceRectHint()` on the `builder` and pass in the `sourceRect` variable.\n\n\n```kotlin\nval context = LocalContext.current\n\nval pipModifier = modifier.onGloballyPositioned { layoutCoordinates -\u003e\n val builder = PictureInPictureParams.Builder()\n if (shouldEnterPipMode) {\n val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()\n builder.setSourceRectHint(sourceRect)\n }\n\n if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.S) {\n builder.setAutoEnterEnabled(shouldEnterPipMode)\n }\n context.findActivity().setPictureInPictureParams(builder.build())\n}\n\nVideoPlayer(pipModifier)https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L218-L233\n```\n\n\u003cbr /\u003e\n\n| **Note:** Depending on the video player you are using, you may need to reference the documentation and choose the `sourceRectHint` that represents the actual video content instead of the full video player."]]