代码: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,使用left和top为Margins的定位参数,只需要给这两个值就可以了((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、状态栏,并根据需要设置屏幕方向。
接口介绍
接口名参数说明

网友评论