Picture in Picture (PiP) improvements

Android 12 introduces behavior improvements and new features for picture-in-picture (PiP) mode.

Behavior improvements for single- and double-tapping

Android 12 has improved PiP behavior for single- and double-tapping, as follows:

  • Single-tapping on a PiP window now displays controls for the user. Previously, a single-tap expanded the PiP window and displayed controls.

  • Double-tapping on a PiP window now toggles between the current PiP size and the maximum PiP size. Previously, a double-tap left PiP mode to full-screen mode.

New features

Android 12 introduces the following new features for PiP mode:

New API flag for smoother transition to PiP mode in gesture navigation

Android 12 lets you use the new setAutoEnterEnabled flag to provide smoother transitions to PiP mode when swiping up to home in gesture navigation mode. Previously, Android waited for the swipe-up-to-home animation to finish before fading in the PiP window.

To implement this feature:

  1. Use setAutoEnterEnabled to construct PictureInPictureParams.Builder, as follows:

    setPictureInPictureParams(new PictureInPictureParams.Builder()
        .setAspectRatio(aspectRatio)
        .setSourceRectHint(sourceRectHint)
        .setAutoEnterEnabled(true)
        .build());
    
  2. Call setPictureInPictureParams with the up-to-date PictureInPictureParams early. The app should not wait for the onUserLeaveHint callback (as it would have done in Android 11).

    For example, an app may want to call setPictureInPictureParams on the very first playback and any following playback if the aspect ratio is changed.

  3. Call setAutoEnterEnabled(false) as needed. For example, it’s probably not optimal for a video app to enter PiP if the current playback is in paused state.

New API flag to disable seamless resizing for non-video content

Android 12 adds the SeamlessResizeEnabled flag, which provides a much smoother cross-fading animation when resizing non-video content in the PiP window. Previously, resizing non-video content in a PiP window could create jarring visual artifacts.

The setSeamlessResizeEnabled flag is set to true by default for backward-compatibility. Leave this set to true for video content, and change it to false for non-video content.

To disable seamless resizing for non-video content:

  setPictureInPictureParams(new PictureInPictureParams.Builder()
          .setSeamlessResizeEnabled(false)
          .build());

Support for smoother animations when exiting out of PiP mode

In Android 12, the SourceRectHint flag is now reused to implement smoother animation when exiting out of PiP mode. On exit, the system creates the animation using the current available sourceRectHint, whether it’s the original Rect used to enter PIP or an updated Rect provided by the app.

To implement this feature, update your app as follows:

  1. Continue to construct PictureInPictureParams with the sourceRectHint and aspectRatio for a smooth entry animation.

  2. If necessary, update the sourceRectHint before the system starts the exit transition. When the system is about to exit PIP mode, the activity’s view hierarchy is laid out to its destination configuration (for example, full screen). The app can attach a layout change listener to its root view or target view (such as the video player view) to detect the event and update the sourceRectHint before the animation begins.

      // Listener is called immediately after the user exits PIP but before animating.
      playerView.addOnLayoutChangeListener { _, left, top, right, bottom,
                           oldLeft, oldTop, oldRight, oldBottom ->
          if (left != oldLeft || right != oldRight || top != oldTop
                  || bottom != oldBottom) {
             // The playerView's bounds changed, update the source hint rect to
             // reflect its new bounds.
             val sourceRectHint = Rect()
             playerView.getGlobalVisibleRect(sourceRectHint)
             setPictureInPictureParams(
                 PictureInPictureParams.Builder()
                     .setSourceRectHint(sourceRectHint)
                     .build()
             )
          }
      }
    

Support for new gestures

Android 12 now supports stashing and pinch-to-zoom gestures for the PiP window:

  • To stash the window, the user can drag the window to the left or right edge. To unstash the window, the user can either tap the visible part of the stashed window or drag it out.

  • The user can now resize the PiP window using pinch-to-zoom.