Android画中画(PIP)模式使用

学更好的别人,

做更好的自己。

——《微卡智享》

21b9ae1a266b55b0e0e9e39a00a5f28d.jpeg

本文长度为1679,预计阅读6分钟

前言

现在手机端各大视频APP基本都有悬浮窗视频模式,我以前文章《Android制作带悬浮窗控制的录屏程序Demo》《Android实现可移动的悬浮窗》有介绍过悬浮窗的使用方式,而到了Android8.0时推出来画中画模式,就是让当前的Activity缩小后显示在其它Activity的上方,使用起来也非常的简单,本篇我们就来试试Android8.0后推出的画中画模式。

46b77aef5685e9462d9fdf79e837445d.png

实现效果

3e63f35a814aacb90938e264ce287026.gif

e7b38eb3d102e16bf6f98c8004939301.jpeg

代码实现

0887132b2eeb0d7e941c3737593ef748.png

微卡智享

画中画设置

在manifests中的activity中加入画中画的配置

f34d515ec61114953a6a8f7bd5752acf.png

<activity
            android:name=".MainActivity"
            android:supportsPictureInPicture="true"
            android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
            android:exported="true">

configchanges这里如果不加参数的话,启动画中画会让activity销毁后重建,这样想要在画中画中更新UI的一些配置是不起作用的。

判断是否能进入画中画模式

665ec7b7ddf5ee729e87085b2f0f620b.png

因为我项目中创建的minsdk是27(android8.1),所以就没再加入判断当前SDK的版本,如果是更小版本可以加入这个判断。

启动画中画模式

aafcbb3b388c6d5c00ac0ef179637026.png

上面这个是默认的构造模式,这个是最简单的启用画中画模式。

监听画中画模式的状态

b2d08b5c7cb45ee30fcd3d75e0e98f9b.png

重写onPictureInPictureModeChanged函数,里面的isInPictureInPictureMode参数是判断当前状态是否是画中画模式,这里代码写的就是当进入画中画模式后,我们TextView中显示为画中画模式,同时画中画的按钮隐藏了,退后时文字改为正常模式,并且按钮也再显示出来。

6d1fc84e897646adebecc5bab588c5b8.png

a49dd70baac832d959f00887abdcfea0.png

正常模式

1731911b84dfda4514b00278213e4a9f.png

bba156e15835533f84015ca0b1a00264.png

da81f10bb098ff8b5e83c4bf4b345bc0.png

画中画模式

1e1d3a12389a2ce7afed0befc6d1e254.png

按钮启动画中画

5c3ea8c9a5fef81ef5e239794b3e4408.png

onCreate事件中加入按钮事件,点击按钮启动画中画模式,这样一个简单的画中画就实现了,确实要比原来做悬浮窗简单多了。

微卡智享

画中画构建器参数问题

上面的画中画启动时构造参数用的是默认的,通过配置构造参数可以实现宽高比例、窗口控件等效果,我们来改造一下代码。

aa306264496c9d902eb4f99b6764dbbf.png

进入画中画模式中加入了actions的按钮,点击后返回到正常模式,然后显示的比例我们由默认的横屏改为竖屏了。

setActions设置控件,基本就是按钮的操作控制。

setAspectRatio设置画中画的宽高比,第一个参数为分子,第二个为分母,指定宽高比,必须在 2.39:1或1:2.39 之间,否则会抛出IllegalArgumentException异常。

Android 12 添加了 setSeamlessResizeEnabled 标志,在画中画窗口中调整非视频内容的大小时,该标志可提供更流畅的交替淡变动画。以前,在画中画窗口中调整非视频内容的大小时会产生烦人的视觉伪影。为了向后兼容,默认情况下,将 setSeamlessResizeEnabled 标志设置为 true。对于视频内容,请将其设置保留为 true;对于非视频内容,请将其更改为 false。

从 Android 12 开始,您可以使用 setAutoEnterEnabled 标志,在手势导航模式下向上滑动转到主屏幕时,更流畅地过渡到画中画模式。所以上图中加入了判断SDK版本设置的参数。

修改参数后的效果

下面两张图是修改了参数后的效果,可以看到原来的横屏改为竖屏了,并且点击后下方还加入了一个按钮。

0d472b1b18b9d72a8af3dc24cfb0420b.png

dec392c9830615eff26f3c065272e9dd.png

完整代码

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
        }
    }


}

155ef72d8014213dc984f2f41a17f20d.png

92c83dc0c7ca6f2e77e9454cd8a342d8.png

往期精彩回顾

20aeb5c9aa87dd92fc2a1676fe26e95d.jpeg

C++ OpenCV手动截取图像做透视变换


89c217f42825b8bc4e611e2ddf7f168f.jpeg

Android前台服务的使用(二)--使用LiveEventBus实现进程间通讯(附源码)

c195d9e13bfbb62f4c16c2f562f0ad0f.jpeg

Android前台服务的使用(一)


猜你喜欢

转载自blog.csdn.net/Vaccae/article/details/127385205