Android 浮窗开发之窗口层级
很多人都知道如何去实现一个简单的浮窗,但是却很少有人去深入的研究背后的流程机制,由于项目中浮窗交互比较复杂,遇到了些坑查看了很多资料,故总结浮窗涉及到的知识点:
- 窗口层级关系(浮窗是如何“浮”的)?
- 浮窗有哪些限制,如何越过用户授权实现浮窗功能?
- 窗口与用户输入系统(Activity是如何接收到touch事件?)。
本章我们来研究第一个问题:浮窗为何会浮。 浮窗之所以叫浮窗,是因为它能悬浮于应用或者桌面窗口之上,能脱离Activity而存在。为了研究其中区别,我们先来看看我们最熟悉的Activity是怎么显示出来的。
Activity是怎么显示出来的?
要弄清这个问题答案,我们先从Activity的setContentView()这个方法的源码开始找起,在Activity中看到setCententView的源码:
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
getWindow是返回返回Activity的mWindow变量,指向一个Window的对象,Window是一个抽象类,这里返回的是PhoneWindow对象(PhoneWindow是Window的子类),PhoneWindow中有一个DecorView对象,decorView成员,这是一个FrameLayout,setContentView的子布局最终会添加到decorView中,这个decorView就是当前窗口的根视图,这个根视图是如何最终被绘制出来的?在ActivityThread中有这样一段代码:
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
这个decorView,最终会被WindowManager.addView添加到绘制系统中,并类型是WindowManager.LayoutParams.TYPE_BASE_APPLICATION,这个参数决定了要绘制的窗口的z轴层次,为了避免思维栈过深,这里就不贴出详细的源码跟踪过程了,直接给结论。
先来看看Activity和window的关系:

再来window和View的关系:

Activity窗口显示过程:

说Activity是怎么显示出来的,其实是说Activity管理的View是怎么显示出来的。最后再来总结一下:
一、Activity通过setContentView设置的视图是添加到PhoneWindow的根视图decor中。
二、Window是一个抽象的概念,Window关了了一个View(根视图),最终被WindowManager管理的还是一个View(根视图)和它的LayoutParams,视图绘制刷新都是通过WindowManager(WindowManagerGlobal)与WindowManagerServiceIPC交互调用底层绘制的。
三、Activity是四大组件中唯一和窗体紧密联系的组件(这是为什么会有初学者把Activity直接理解为绘制界面的原因),所有掌管的视图只不过是一种window和Dialog、Toast、墙纸所掌管的Window类型不一样。
浮窗为什么会“浮”?
上面讲到Activity的显示过程其实已经揭示了通用界面的显示过程,浮窗的显示过程更为简单:

做过浮窗的同学应该都明白了,为啥浮窗能脱离Activity而显示,本质上我们是把一个View交给WindowManager来管理了,LayoutParams.type类型决定了这个View显示窗口的类型,不同类型显示的窗口层次(z轴)是不一样的。大方面来讲可以分为应用窗口(APPLICATION_WINDOW)、子窗口(SUB_WINDOW)、系统窗口(SYSTEM_WINDOW)三种类型,应用窗口z轴范围是1~99,子窗口的范围是1001~1999,系统窗口是(2000~2999),所以要实现浮动窗口我们只能在系统窗口范围中实现。
| 类型 | 常量范围 | 子类 | 常量值 | 说明 | 例子 |
| APPLICATION_WINDOW | 1~99 | TYPE_BASE_APPLICATION | 1 | ||
| TYPE_APPLICATION | 2 | 应用窗口 | 大部分的应用程序窗口 | ||
| TYPE_APPLICATION_STARTING | 3 | 应用程序的Activity显示之前由系统显示的窗口 | |||
| LAST_APPLICATION_WINDOW | 99 | ||||
| SUB_WINDOW | 1000~1999 | FIRST_SUB_WINDOW | 1000 | ||
| TYPE_APPLICATION_PANEL | 1000 | 显示在母窗口之上,遮挡其下面的应用窗口。 | |||
| TYPE_APPLICATION_MEDIA | 1001 | 显示在母窗口之下,如果应用窗口不挖洞,即不可见。 | SurfaceView,在小窗口显示时设为MEDIA, 全屏显示时设为PANEL | ||
| TYPE_APPLICATION_SUB_PANEL | 1002 | ||||
| TYPE_APPLICATION_ATTACHED_DIALOG | 1003 | ||||
| TYPE_APPLICATION_MEIDA_OVERLAY | 1004 | 用于两个SurfaceView的合成,如果设为MEDIA,则上面的SurfaceView 挡住下面的SurfaceView | |||
| SYSTEM_WINDOW | 2000~2999 | TYPE_STATUS_BAR | 2000 | 顶部的状态栏 | |
| TYPE_SEARCH_BAR | 2001 | 搜索窗口,系统中只能有一个搜索窗口 | |||
| TYPE_PHONE | 2002 | 电话窗口 | |||
| TYPE_SYSTEM_ALERT | 2003 | 警告窗口,在所有其他窗口之上显示 | 电量不足提醒窗口 | ||
| TYPE_KEYGUARD | 2004 | 锁屏界面 | |||
| TYPE_TOAST | 2005 | 短时的文字提醒小窗口 | |||
| TYPE_SYSTEM_OVERLAY | 2006 | 没有焦点的浮动窗口 | |||
| TYPE_PRIORITY_PHONE | 2007 | 紧急电话窗口,可以显示在屏保之上 | |||
| TYPE_SYSTEM_DIALOG | 2008 | 系统信息弹出窗口 | 比如SIM插上后弹出的运营商信息窗口 | ||
| TYPE_KEYGUARD_DIALOG | 2009 | 跟KeyGuard绑定的弹出对话框 | 锁屏时的滑动解锁窗口 | ||
| TYPE_SYSTEM_ERROR | 2010 | 系统错误提示窗口 | ANR 窗口 | ||
| TYPE_INPUT_METHOD | 2011 | 输入法窗口,会挤占当前应用的空间 | |||
| TYPE_INPUT_METHOD_DIALOG | 2012 | 弹出的输入法窗口,不会挤占当前应用窗口空间,在其之上显示 | |||
| TYPE_WALLPAPER | 2013 | 墙纸 | |||
| TYPE_STATUS_BAR_PANEL | 2014 | 从状态条下拉的窗口 | |||
| TYPE_SECURE_SYSTEM_OVERLAY | 2015 | 只有系统用户可以创建的OVERLAY窗口 | |||
| TYPE_DRAG | 2016 | 浮动的可拖动窗口 | 360安全卫士的浮动精灵 | ||
| TYPE_STATUS_BAR_PANEL | 2017 | ||||
| TYPE_POINTER | 2018 | 光标 | |||
| TYPE_NAVIGATION_BAR | 2019 | ||||
| TYPE_VOLUME_OVERLAY | 2020 | 音量调节窗口 | |||
| TYPE_BOOT_PROGRESS | 2021 | 启动进度,在所有窗口之上 | |||
| TYPE_HIDDEN_NAV_CONSUMER | 2022 | 隐藏的导航栏 | |||
| TYPE_DREAM | 2023 | 屏保动画 | |||
| TYPE_NAVIGATION_BAR_PANEL | 2024 | Navigation bar 弹出的窗口 | 比如说应用收集栏 | ||
| TYPE_UNIVERSAL_BACKGROUND | 2025 | ||||
| TYPE_DISPLAY_OVERLAY | 2026 | 用于模拟第二显示设备 | |||
| TYPE_MAGNIFICATION | 2027 | 用于放大局部 | |||
| TYPE_RECENTS_OVERLAY | 2028 | 当前应用窗口,多用户情况下只显示在用户节目 |
Android 浮窗开发之窗口层级的更多相关文章
- Android浮窗权限研究(转载)
这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时 ...
- Android 悬浮窗、悬浮球开发
原文:Android 悬浮窗.悬浮球开发 1.权限管理 直接看我另外一篇博客吧,传送门: https://my.oschina.net/u/1462828/blog/1933162 2.Base类Ba ...
- Android悬浮窗实现 使用WindowManager
Android悬浮窗实现 使用WindowManager WindowManager介绍 通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得 ...
- 浮窗WindowManager view返回和Home按键事件监听
出于功能需求,需要在所有的view之上显示浮窗,于是需要在WindowManager的View上处理返回键的响应, mFloatingWindowView = layoutInflater.infla ...
- Android 使用WindowManager实现Android悬浮窗
WindowManager介绍 通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得 WindowManager对象. 每一个WindowMan ...
- Android之NDK开发(转)
Android之NDK开发 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...
- Android移动APP开发笔记——最新版Cordova 5.3.1(PhoneGap)搭建开发环境
引言 简单介绍一下Cordova的来历,Cordova的前身叫PhoneGap,自被Adobe收购后交由Apache管理,并将其核心功能开源改名为Cordova.它能让你使用HTML5轻松调用本地AP ...
- Android之NDK开发
转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...
- 关于Android悬浮窗要获取按键响应的问题
要在Android中实现顶层的窗口弹出,一般都会用WindowsManager来实现,但是几乎所有的网站资源都是说弹出的悬浮窗不用接受任何按键响应. 而问题就是,我们有时候需要他响应按键,比如电视上的 ...
随机推荐
- 你真的会玩SQL吗?和平大使 内连接、外连接
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- Notepad++ 实用技巧
Notepad++是一款开源的文本编辑器,功能强大.很适合用于编辑.注释代码.它支持绝大部分主流的编程语言. 本文主要列举了本人在实际使用中遇到的一些技巧. 快捷键 自定义快捷键 首先,需要知道的是: ...
- 【神器】vimum在浏览器中键盘操作选择、复制、粘贴,键盘党的最爱
1.下载: http://files.cnblogs.com/files/quejuwen/vimum_extension_1_56.zip 2.开源:https://github.com/philc ...
- css水平居中的各种方法
说到水平居中,大家可能觉得很简单啊,text-align:center 就OK了. 但是,有时候会发现这样写了也没出效果.原因是什么呢? 请往下看. 水平居中:分为块级元素居中和行元素居中 行内元素 ...
- html文本垂直居中对齐
html文本垂直居中对齐,代码如下: <div id="box" style="height:100px; line-height:100px; border:1p ...
- Java中的多线程你只要看这一篇就够了
学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 引 如果对什么是线程.什么是进程仍存有疑惑, ...
- linux(七)__shell脚本编程
一.什么是shell脚本 shell除了是命令解释器之外还是一种编程语言,用shell编写的程序类似于DOS下的批处理程序. 它是用户与操作系统之间的一个接口. shell脚本语言非常擅长处理文本类型 ...
- div仿textarea使高度自适应
今天真的有些无语,在百度上找了很多关于textarea和input高度自适应的代码,并且考虑到了要判断textarea的滚动条,从而动态改变它的高度,直到我搜索了这个让我目瞪狗呆的办法…… <d ...
- SQL通过ContentTypeID找使用了内容类型的列表库
DECLARE) SET @ContentTypeID='0x1B452DB25E92A34DA3E35FC8731278D2' SELECT w.Title AS [Web Site], w.Ful ...
- iOS开发--Swift RAC响应式编程初探
时间不是很充足, 先少说点, RAC的好处是响应式编程, 不需要自己去设置代理委托, target, 而是主要以信息流(signal), block为主, 看到这里激动吧, 它可以帮你监听你的事件, ...