很多人都知道如何去实现一个简单的浮窗,但是却很少有人去深入的研究背后的流程机制,由于项目中浮窗交互比较复杂,遇到了些坑查看了很多资料,故总结浮窗涉及到的知识点:

  • 窗口层级关系(浮窗是如何“浮”的)?
  • 浮窗有哪些限制,如何越过用户授权实现浮窗功能?
  • 窗口与用户输入系统(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 浮窗开发之窗口层级的更多相关文章

  1. Android浮窗权限研究(转载)

    这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时 ...

  2. Android 悬浮窗、悬浮球开发

    原文:Android 悬浮窗.悬浮球开发 1.权限管理 直接看我另外一篇博客吧,传送门: https://my.oschina.net/u/1462828/blog/1933162 2.Base类Ba ...

  3. Android悬浮窗实现 使用WindowManager

    Android悬浮窗实现 使用WindowManager WindowManager介绍 通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得  ...

  4. 浮窗WindowManager view返回和Home按键事件监听

    出于功能需求,需要在所有的view之上显示浮窗,于是需要在WindowManager的View上处理返回键的响应, mFloatingWindowView = layoutInflater.infla ...

  5. Android 使用WindowManager实现Android悬浮窗

    WindowManager介绍 通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得 WindowManager对象. 每一个WindowMan ...

  6. Android之NDK开发(转)

    Android之NDK开发 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...

  7. Android移动APP开发笔记——最新版Cordova 5.3.1(PhoneGap)搭建开发环境

    引言 简单介绍一下Cordova的来历,Cordova的前身叫PhoneGap,自被Adobe收购后交由Apache管理,并将其核心功能开源改名为Cordova.它能让你使用HTML5轻松调用本地AP ...

  8. Android之NDK开发

    转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...

  9. 关于Android悬浮窗要获取按键响应的问题

    要在Android中实现顶层的窗口弹出,一般都会用WindowsManager来实现,但是几乎所有的网站资源都是说弹出的悬浮窗不用接受任何按键响应. 而问题就是,我们有时候需要他响应按键,比如电视上的 ...

随机推荐

  1. Azure Backup (3) 使用Azure备份服务,备份Azure虚拟机

    <Windows Azure Platform 系列文章目录> 本将介绍,如何使用Azure备份服务,备份Azure虚拟机. 我们先预先创建2台Windows VM (命名为LeiVM00 ...

  2. DOM 事件深入浅出(一)

    在项目开发时,我们时常需要考虑用户在使用产品时产生的各种各样的交互事件,比如鼠标点击事件.敲击键盘事件等.这样的事件行为都是前端DOM事件的组成部分,不同的DOM事件会有不同的触发条件和触发效果.本文 ...

  3. GridView详细介绍

    GridView控件的属性 表10.6 GridView控件的行为属性属性描述AllowPaging指示该控件是否支持分页.AllowSorting指示该控件是否支持排序.AutoGenerateCo ...

  4. No.004:Median of Two Sorted Arrays

    问题: There are two sorted arrays nums1 and nums2 of size m and n respectively.Find the median of the ...

  5. 推荐书单(转自GITHUB)

    Skip to content PersonalOpen sourceBusinessExplore Sign upSign in PricingBlogSupport   This reposito ...

  6. Quartz框架(第一版)

    任务调度 在企业级应用中,经常会制定一些"计划任务",即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发.线程池维 ...

  7. JavaScript执行环境

    执行环境(Execution Context,也称为"执行上下文")是JavaScript中最为重要的一个概念.执行环境定义了变量或函数有权访问的其它数据,决定了各自的行为.当Ja ...

  8. HTML学习(零)简介

    一)HTML介绍 它是一个超文本标记语言,静态页面. 所谓的'超文本'就是指页面内可以包含图片.链接,甚至音乐.程序等非文字元素. 主要的结构为包括"头"部分(英语:Head).和 ...

  9. MapReduce 的架构

    主从结构 主节点,只有一个 : JobTracker   ,JobTracker 一般情况下,运行在 namenode 这台机器上. 从节点,有很多个 : TaskTrackers  ,  部署在剩下 ...

  10. gulp rev manifest 添加目录前缀

    gulp-rev 生成的manifest默认为: "index.css": "index.css?v=04aff97a7b", 为避免同名文件覆盖版本号,对替换 ...