画中画功能
Android 8.0 Oreo(API Level 26)允许活动启动画中画 Picture-in-picture(PIP)模式,我就是采用官方api模式实现,还有一种实现方案采用的是window方式,我项目里采用的是第三方播放器感觉用window方式实现困难了些不好衔接。
具体实现很简单就几点 就是参照的官方文档
1在你的manifest配置文件配置你的播放类acitvity
<activity android:name="VideoActivity"
android:supportsPictureInPicture="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
2在播放器控制栏添加的一个小窗播放按钮(参考爱奇艺) 点击按钮进入画中画模式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PictureInPictureParams.Builder pictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
mVideoWith = Player.getVideoWidth();
mVideoHeight = Player.getVideoHeight();
if (mVideoWith != 0 && mVideoHeight != 0) {
Rational aspectRatio = new Rational(mVideoWith, mVideoHeight);
pictureInPictureParamsBuilder.setAspectRatio(aspectRatio);
}
//进入pip
enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
}
3监听进入退出画中画
@Override
public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) {
if (isInPictureInPictureMode) {
// 进入画中画 这里隐藏全屏播放的ui
} else {
// 退出画中画 这里显示ui
}
}
@Override
public void onUserLeaveHint() {
/ /当点击home键会触发这个方法,这里也可以调用进入画中画 看需求,我这里没有些写任何代码
}
官方文档写的大概也是这些
总结下完成功能后遇到的几个问题
1 切换画中画 小屏会白一小会 才显示继续播放的视频我用的小米手机测试的,查看官方文档有写到
Android 12 对全屏窗口和画中画窗口之间的动画过渡效果进行了重大改进
从 Android 12 开始,PictureInPictureParams.Builder.setAutoEnterEnabled(true) 标志可提供更流畅的动画,用于在画中画模式下使用手势导航过渡到视频内容(例如,从全屏向上滑动到主屏幕时)。如果您的应用属于 ENTERTAINMENT、COMMUNICATION 或 VIDEO_PLAYER 应用类别,我们建议您采用此方式。
我是基于Android11做的没有setAutoEnterEnabled这个方法,但文档中还提供另一个方法
在 Android 8.0 中引入画中画功能时,sourceRectHint 用于指明在转换为画中画之后可见的 activity 区域,例如视频播放器中的视频视图边界。从 Android 12 开始,操作系统使用 sourceRectHint 在进入和退出画中画模式时实现更流畅的动画。
如果您的应用未提供适当的 sourceRectHint,画中画过渡仍正常运行,但动画不够精美
所以设置sourceRectHint 这个方法解决了这个问题
Rect rect = new Rect();
PlayerView.getGlobalVisibleRect(rect);
pictureInPictureParamsBuilder.setSourceRectHint(rect);
2 切换画中画模式变成小屏后 页面会自动回到上一个页面,但是这个页面的布局会乱,页面控件变大了,一开始我以为是我引用的AndroidAutoSize 适配框架的原因 ,他们有冲突毕竟这个框架是全局适配的,后来发现不是 。
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
在切换画中画自动回到的上个页面activity也都配置上面属性,解决了这个问题
3 在画中画模式下操作别的功能 进入别的页面 有的页面直接在画中画小窗里打开了,这个是因为你打开的页面activity启动模式android:launchMode="singleTask" 把他去掉就好
4 在画中画模式下 在点击别的视频进入播放页面,由于我的播放页面是上面视频下tablyout+viewpager+fragment 根据不同需求 视频下面的fragment数量不一样 有的两个tab 有的三个,当三个进两个时java.lang.IllegalStateException:ViewPager: Can't Change Tag of Fragment出现这个异常,当两个进三个时下面fragment没有更新 ,我明明已经clear掉集合里的fragment了,原来是因为viewpager在加载当前页的时候已经将pager页左右页的内容加载进内存里了,并没有真正的删除,出现异常应该应该是一个位置有两个相同tag的fragment。
解决方案
将FragmentPagerAdapter 替换成FragmentStatePagerAdapter,因为前者只要加载过,fragment中的视图就一直在内存中,在这个过程中无论你怎么刷新,清除都是无用的,直至程序退出; 后者可实现真正删除。
重写Adapter的方法--getItemPosition(),让其返回PagerAdapter.POSITION_NONE
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
进入新的播放页面会触发onNewIntent
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//获取视频url
//重置viewpager fragment 等大概逻辑,如果视频是进入画中画模式之前的视频 这里可以不做任何处理
}
5 点击画中画小屏的关闭按钮要关闭activity,这个点击关闭按钮会除非 播放类activity的 onStop方法 利用这个加个变量判断
@Override
protected void onStop() {
super.onStop();
closePip = true;
}
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
if(isInPictureInPictureMode){
}else {
if(closePip){
finish();
}
}
}