Android 原生 Picture in Picture 画中画功能避坑指南 您所在的位置:网站首页 安卓设置弹窗怎么关闭啊苹果手机 Android 原生 Picture in Picture 画中画功能避坑指南

Android 原生 Picture in Picture 画中画功能避坑指南

2023-06-07 23:52| 来源: 网络整理| 查看: 265

最近生活有些变动所以断更好久,不过虽迟到但永远不会缺席。ChatGPT 浪潮还在持续扩大,各位同学一定要体验体验丫~

这篇主要介绍最近需求中遇到的问题,希望能帮助后来者少踩坑。先说结论:Android 原生画中画功能并不完善,如果可以接受 APP 有两个任务栈则可以使用;否则趁早自己用浮窗自定义实现画中画的功能吧。

1. PiP 简介

Android PiP 模式也称之为画中画模式,允许用户在使用应用程序的同时,在屏幕的一角或一侧浮动显示另一个应用程序或视频。这使得用户可以同时进行多项任务,而不必切换应用程序或中断正在进行的任务。如下所示:

图 1 PiP示例 (注:B站的 PiP 是自定义实现的,未使用系统 PiP)

2. 准备工作,跑通 Demo

官方文档:developer.android.google.cn/guide/topic… 官方Demo:github.com/android/med…

打开官方 Demo,首先得改一下 minSdkVersion,demo 里设置的是 API 31(Android 12.0),不满足实际应用需求,这里改为 23(Android 6.0). 但 PiP 功能只能在 Android8.0 及以上的系统上使用,所以用到一些方法时,需要注明 @RequiresApi(Build.VERSION_CODES.O)。所以,如果需要在 Android 8.0 以下的设备支持 PiP,只能使用自定义悬浮窗实现。

还需要注释掉 setAutoEnterEnabled(true)、setSeamlessResizeEnabled(false) 这两个方法。因为它们只能在 Android 12.0 及以上系统使用,且对于 PiP 的主体功能没有影响。setAutoEnterEnabled 用于设置 Activity 在退到后台时是否自动进入 PiP 模式,当设置为 true,则在用户点击 Home 键回到主屏幕时,Activity 可自动进入 PiP 模式,而不用开发者手动调用 enterPictureInPictureMode 方法;setSeamlessResizeEnabled 用于设置非视频画中画时的动画效果,不影响功能。

按照上述的内容设置完后就可以将 Demo 跑通了。

3. 示例代码分析

仅分析查看了 Demo 中的 MovieActivity 中的 PiP 相关的代码。比较重要的代码如下:

// code 1 @RequiresApi(Build.VERSION_CODES.O) private fun minimize() { enterPictureInPictureMode(updatePictureInPictureParams()) }

调用 enterPictureInPictureMode(@NonNull PictureInPictureParams params) 方法就可以进入 PiP,声明如下:

// code 2 public boolean enterPictureInPictureMode(@NonNull PictureInPictureParams params) { ··· }

方法简介:它是 Activity 类中的方法,需要传递一个 PictureInPictureParams 类型对象。当系统成功将该 Activity 切换到 PiP 模式或已经处于 PiP,则返回值为 true;如果设备不支持 PiP 则返回 false。

再来看下构建 PictureInPictureParams 类型对象的 updatePictureInPictureParams() 方法:

// code 3 @RequiresApi(Build.VERSION_CODES.O) private fun updatePictureInPictureParams(): PictureInPictureParams { // 1、计算出 PiP 小窗的宽高比,这里直接使用播放视频的控件宽和高计算 val aspectRatio = Rational(binding.movie.width, binding.movie.height) // 2、将播放视频的控件binding.movie设置为 PiP 中要展示的部分 val visibleRect = Rect() binding.movie.getGlobalVisibleRect(visibleRect) val params = PictureInPictureParams.Builder() .setAspectRatio(aspectRatio) // 3、指定进入画中画的屏幕部分。系统根据这个可实现平滑动画效果。这里就把之前生成的 visibleRect 传值过去 .setSourceRectHint(visibleRect) .build() setPictureInPictureParams(params) return params }

updatePictureInPictureParams 方法作用是构建出进入 PiP 的一些参数,比如进入小窗的控件,小窗的宽高比等。注释很清楚,源码直接拿来套用就行。需要注意的点:只能指定 PiP 模式的宽高比,并不能直接设置宽和高的具体值,系统会根据设置的宽高比自己计算具体值。

如果在播放器控件上层有其他的操作按钮等,还需要在 onPictureInPictureModeChanged 回调中进行处理,即进入 PiP 后隐藏这些按钮;退出后恢复这些按钮的状态。 如下是 Demo 中的实现:

// code 4 override fun onPictureInPictureModeChanged( isInPictureInPictureMode: Boolean, newConfig: Configuration ) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) if (isInPictureInPictureMode) { // Hide the controls in picture-in-picture mode. binding.movie.hideControls() } else { // Show the video controls if the video is not playing if (!binding.movie.isPlaying) { binding.movie.showControls() } } }

通过这个方法可以监听 PiP 的进入和退出。

还有一些是 PiP 模式下的播放/暂停、上一个/下一个 操作按钮,即下图红框中的这三个按钮,相关的使用方式 Demo 中已有示例,这里不再赘述。

图1 PiP按钮示意图

除此之外,还要在需要进入 PiP 的 Activity 的 AndroidManifest 中设置支持 PiP 的属性以及处理布局配置更改。这样一来,如果在 PiP 模式转换期间出现布局更改,该 Activity 就不会重新启动。

// code 5


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有