美文网首页Android直播
可无缝切换小窗/全屏的android播放器实现

可无缝切换小窗/全屏的android播放器实现

作者: 浪里_个郎 | 来源:发表于2020-03-11 20:36 被阅读0次

代码:https://github.com/zackLangChina/AutoMonitorPlayer

效果:

普通模式多画面 / 全屏播放 小窗模式

布局和拖拽功能介绍

普通窗口下的视图层级关系  

将AutoMonitorPlayer作为控件时,layout图层关系如上图。AutoMonitorPlayer内部包含一个FrameLayout,将SurfaceView包含在内。

页面小窗

当切换到小窗模式时,AutoMonitorPlayer将容器Framelayout删除出子节点,外部的根节点android.R.id.content再将容器FrameLayout加为子节点:

//父节点变了,需要从老的父节点处删掉容器

this.removeView(mContainer);

//android.R.id.content是MainActivity布局最外面的一层FrameLayout

ViewGroup contentView =(ViewGroup)NiceUtil.scanForActivity(mContext).findViewById(android.R.id.content);

FrameLayout.LayoutParams params =mConfig.getTinyWindowLayoutParams();contentView.addView(mContainer,params);

关于小窗的拖拽,自定义继承自FrameLayout的类(DragFrameLayout)作为SurfaceView容器类,接收到onTouch回调的移动消息后,调用layout修改自己的位置,接收到up消息后,调用setLayoutParams修改自身窗口参数:

//临时修改视图显示

layout(oriLeft,oriTop,oriRight,oriBottom);

//这里修改gravity,使用lefttopMargins的定位参数,只需要给这两个值就可以了((LayoutParams)oldParams).gravity = Gravity.LEFT | Gravity.TOP;((LayoutParams)oldParams).setMargins(oriLeft,oriTop,0,0);setLayoutParams(oldParams);

必须要说明的是,目前这种实现方式,小窗还是和页面绑定的。如果要全局窗口,需要新建全局弹窗,再将FrameLayout作为该全局弹窗的视图子节点。

全局小窗

全局窗口需要使用AlertDialog(TinyDialog):

getWindow().getAttributes().type =  WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

使用AlertDialog要注意权限的申请,除了AndroidManifest.xml中申明权限,如果是android6.0以上的SDK,还需要在代码中动态申请权限:

context.startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,        Uri.parse("package:" + context.getPackageName())), 0);

创建了全局窗口,我们就要把FrameLayout容器放入这个窗口:

mTinyDialg.addContentView(mContainer,new FrameLayout.LayoutParams(        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

如图,和页面内小窗比较类似,不同的是AlertDiaolg不再属于应用中的布局,即使切出应用也可见。

关于全局小窗的拖拽。页面小窗其实改变的是Framelayout的窗口位置,而全局小窗改变的是AlertDialog的窗口位置。

有一点很重要,我们知道Android有一套触摸消息传递机制,默认情况下会先传递给子布局,如果消息没有被消费掉,再一层层往上传递。AlertDialog作为FrameLayout的父节点,要想优先消费触摸消息,必须进行消息拦截,要覆写dispatchTouchEvent方法:

@Overridepublic boolean dispatchTouchEvent(@NonNull MotionEvent ev) {    return onTouchEvent(ev);}

然后根据触摸坐标确定要移动到哪里,再通过WindowManager改变自己的位置:

mWindowManager.updateViewLayout(getWindow().getDecorView(), layoutParams);

全屏

全屏时,同样是AutoMonitorPlayer将容器Framelayout删除出子节点,外部的根节点android.R.id.content再将容器FrameLayout加为子节点,同时,需要隐藏ActionBar、状态栏,并根据需要设置屏幕方向。

接口介绍

接口名参数说明

相关文章

网友评论

    本文标题:可无缝切换小窗/全屏的android播放器实现

    本文链接:https://www.haomeiwen.com/subject/qkfbqhtx.html