Android的界面绘制和编程,都是通过WindowManager来实现的,而我们要在应用之外绘制一个悬浮框,自然也离不开WindowManager
首先在编程之前,要确定是否要相应的权限
还可以通过Settings.ACTION_MANAGE_OVERLAY_PERMISSION检查权限,并且让用户手动打开权限
WindowManager中实现了viewpager的接口,而viewpager中有个addview的方法,添加的view就是我们要显示的悬浮框
而WindowManager的addview有两个参数,一个是要加入的view,一个是WindowManager.layoutParam对象,这个对象包含了是否全屏,以及是否拦截触摸事件的参数
同时要注意的是layoutParam中的type变量是用来指定窗口类型的,在设置变量时需要注意区分不同的Android版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
在Android8.0以上的版本,如果还是使用TYPE_PHONE那么将会报异常
而在启动悬浮框时,为了让悬浮框和activity或者Fragment脱离,让其在应用处于后台时依旧能够正常使用,将采用service的方式来启动悬浮框
在启动之前,先用StartActivityForResult查询权限,然后再ActivityResult中获取返回的值来判断是否拥有权限,然后通过startservice启动服务
在service页面中初始化windowManager
val windowmanager= context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
获取需要添加的view
view = LayoutInflater.from(this).inflate(R.layout.float_view, null)
然后通过layoutparams添加
layoutParams = new WindowManager.LayoutParams();
layoutParams.flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
......
需要注意的是,关闭悬浮框时要remove,还不是单纯的stopservice,因为那样会导致悬浮框依旧存在于窗口之中