学更好的别人,
做更好的自己。
——《微卡智享》
本文长度为1679字,预计阅读6分钟
前言
现在手机端各大视频APP基本都有悬浮窗视频模式,我以前文章《Android制作带悬浮窗控制的录屏程序Demo》《Android实现可移动的悬浮窗》有介绍过悬浮窗的使用方式,而到了Android8.0时推出来画中画模式,就是让当前的Activity缩小后显示在其它Activity的上方,使用起来也非常的简单,本篇我们就来试试Android8.0后推出的画中画模式。
实现效果
代码实现
![0887132b2eeb0d7e941c3737593ef748.png](https://i-blog.csdnimg.cn/blog_migrate/613f1ad9f3a1169f784755a722fca0ac.png)
微卡智享
画中画设置
在manifests中的activity中加入画中画的配置
<activity
android:name=".MainActivity"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="true">
configchanges这里如果不加参数的话,启动画中画会让activity销毁后重建,这样想要在画中画中更新UI的一些配置是不起作用的。
判断是否能进入画中画模式
因为我项目中创建的minsdk是27(android8.1),所以就没再加入判断当前SDK的版本,如果是更小版本可以加入这个判断。
启动画中画模式
上面这个是默认的构造模式,这个是最简单的启用画中画模式。
监听画中画模式的状态
重写onPictureInPictureModeChanged函数,里面的isInPictureInPictureMode参数是判断当前状态是否是画中画模式,这里代码写的就是当进入画中画模式后,我们TextView中显示为画中画模式,同时画中画的按钮隐藏了,退后时文字改为正常模式,并且按钮也再显示出来。
正常模式
画中画模式
按钮启动画中画
onCreate事件中加入按钮事件,点击按钮启动画中画模式,这样一个简单的画中画就实现了,确实要比原来做悬浮窗简单多了。
微卡智享
画中画构建器参数问题
上面的画中画启动时构造参数用的是默认的,通过配置构造参数可以实现宽高比例、窗口控件等效果,我们来改造一下代码。
进入画中画模式中加入了actions的按钮,点击后返回到正常模式,然后显示的比例我们由默认的横屏改为竖屏了。
setActions设置控件,基本就是按钮的操作控制。
setAspectRatio设置画中画的宽高比,第一个参数为分子,第二个为分母,指定宽高比,必须在 2.39:1或1:2.39 之间,否则会抛出IllegalArgumentException异常。
Android 12 添加了 setSeamlessResizeEnabled 标志,在画中画窗口中调整非视频内容的大小时,该标志可提供更流畅的交替淡变动画。以前,在画中画窗口中调整非视频内容的大小时会产生烦人的视觉伪影。为了向后兼容,默认情况下,将 setSeamlessResizeEnabled 标志设置为 true。对于视频内容,请将其设置保留为 true;对于非视频内容,请将其更改为 false。
从 Android 12 开始,您可以使用 setAutoEnterEnabled 标志,在手势导航模式下向上滑动转到主屏幕时,更流畅地过渡到画中画模式。所以上图中加入了判断SDK版本设置的参数。
修改参数后的效果
下面两张图是修改了参数后的效果,可以看到原来的横屏改为竖屏了,并且点击后下方还加入了一个按钮。
完整代码
package dem.vaccae.androidpipdemo
import android.app.PendingIntent
import android.app.PictureInPictureParams
import android.app.RemoteAction
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.drawable.Icon
import android.opengl.Visibility
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Rational
import android.view.View
import android.widget.Toast
import dem.vaccae.androidpipdemo.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.textView.text = "正常模式"
binding.btnpip.setOnClickListener {
if (isCanPipModel()) {
enterPipModel()
} else {
Toast.makeText(this, "无法进入PIP模式", Toast.LENGTH_SHORT)
.show()
}
}
}
//判断是否可以进入画中画模式
private fun isCanPipModel(): Boolean {
return packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
}
private fun enterPipModel() {
val builder = PictureInPictureParams.Builder()
//设置Actions
val pIntent = PendingIntent.getActivity(this,100,
intent,PendingIntent.FLAG_UPDATE_CURRENT)
val remoteAction = RemoteAction(Icon.createWithResource(this,
R.mipmap.ic_launcher), "画中画","Vaccae",pIntent)
builder.setActions(arrayListOf(remoteAction))
//设置宽高比例,第一个是分子,第二个是分母,指定宽高比,必须在 2.39:1或1:2.39 之间,否则会抛出IllegalArgumentException异常。
val rational= Rational(3,7)
builder.setAspectRatio(rational)
//Android12下加入的画中画配置,对于非视频内容停用无缝大小调整
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setSeamlessResizeEnabled(false)
builder.setAutoEnterEnabled(true)
}
enterPictureInPictureMode(builder.build())
}
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration?
) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
if (isInPictureInPictureMode) {
binding.textView.text = "画中画模式"
binding.btnpip.visibility = View.GONE
} else {
binding.textView.text = "正常模式"
binding.btnpip.visibility = View.VISIBLE
}
}
}
完
往期精彩回顾
Android前台服务的使用(二)--使用LiveEventBus实现进程间通讯(附源码)