Android WindowManager类

1. Window和WindowManager

Window有三种类型,层级大的会覆盖在层级小的上面

  • 应用Window,对应Activity,层级范围是 1~99
  • Window,对应DialogPopupWindow,层级范围是 1000~1999
  • 系统Window,对应Toast层级范围是 2000~2999

WindowManager继承ViewManager,可以显示类似悬浮窗效果,主要实现下面三个方法

public interface ViewManager {
    public void addView(View view, ViewGroup.LayoutParams params); 
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

2. 创建悬浮窗

悬浮窗对应系统Window,通过WindowManager.addView(View, ViewGroup.LayoutParams)加入界面

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL; // 窗口位置
lp.format = PixelFormat.TRANSPARENT; // 位图格式
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; // 窗口的层级关系
lp.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 窗口的模式
wm.addView(view, lp);

WindowManager.LayoutParamstype属性取值

常量 含义
FIRST_APPLICATION_WINDOW 应用程序窗口
TYPE_BASE_APPLICATION 所有程序窗口的“基地”窗口
TYPE_APPLICATION 普通应用功能程序窗口
TYPE_APPLICATION_STARTING 用于应用程序启动时所显示的窗口
LAST_APPLICATION_WINDOW 应用程序窗口结束
FIRST_SUB_WINDOW 子窗口
TYPE_APPLICATION_PANE 面板窗口
TYPE_APPLICATION_MEDIA 媒体窗口
TYPE_APPLICATION_SUB_PANEL 应用程序窗口的子面板
TYPE_APPLICATION_ATTACHED_DIALOG 对话框
TYPE_APPLICATION_MEDIA_OVERLAY 媒体信息
LAST_SUB_WINDOW 子窗口结束
FIRST_SYSTEM_WINDOW 系统窗口
TYPE_STATUS_BAR 状态栏
TYPE_SEARCH_BAR 搜索栏
TYPE_PHONE 电话窗口
TYPE_SYSTEM_ALERT 系统提示
TYPE_KEYGUARD 锁屏窗口
TYPE_TOAST 信息窗口
TYPE_SYSTEM_OVERLAY 系统顶层窗口
TYPE_PRIORITY_PHONE 电话优先,当锁屏时显示
TYPE_SYSTEM_DIALOG 系统对话框(例如音量调节框)
TYPE_KEYGUARD_DIALOG 锁屏时显示的对话框
TYPE_SYSTEM_ERROR 系统内部错误提示,显示于所有内容之上
TYPE_INPUT_METHOD 内部输入法窗口,显示于普通UI之上
TYPE_INPUT_METHOD_DIALOG 内部输入法对话框,显示于当前输入法窗口之上
TYPE_WALLPAPER 墙纸窗口
TYPE_STATUS_BAR_PANEL 状态栏的滑动面板
LAST_SYSTEM_WINDOW 系统窗口结束

WindowManager.LayoutParamsflags属性取值

常量 含义
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON 允许在屏幕开启的时候锁定屏幕
FLAG_DIM_BEHIND window会变暗,使用dimAmount属性来控制变暗的程度
FLAG_NOT_FOCUSABLE window永远不会获取焦点
FLAG_NOT_TOUCHABLE window永远无法获取点击事件
FLAG_NOT_TOUCH_MODAL 允许window之外点击事件传递给其他在其之后的window
FLAG_TOUCHABLE_WHEN_WAKING device休眠的时候,当触摸屏被点击,window会收到首次点击事件
FLAG_KEEP_SCREEN_ON 当这个window对用户是可见状态,保持设备屏幕不关闭且不变暗
FLAG_LAYOUT_IN_SCREEN 将window放置在整个屏幕之内,无视其他的装饰
FLAG_LAYOUT_NO_LIMITS 允许window扩展至屏幕之外
FLAG_FULLSCREEN 当这个window显示的时候,隐藏所有的装饰物
FLAG_FORCE_NOT_FULLSCREEN 覆盖FLAG_FULLSCREEN效果,并强制显示屏幕上的一些装饰
FLAG_SECURE 把这个window中的内容看作需要保护的内容,防止被截屏
FLAG_SCALED 一种特殊模式,布局参数用于指示显示比例
FLAG_IGNORE_CHEEK_PRESSES 会过滤不需要的点击事件
FLAG_LAYOUT_INSET_DECOR 这个flag只能配合 FLAG_LAYOUT_IN_SCREEN 一起使用
FLAG_ALT_FOCUSABLE_IM 反转FLAG_NOT_FOCUSABLE选项
FLAG_WATCH_OUTSIDE_TOUCH 一个点击事件如果发生在你的window之外的范围,你就会接收到一个特殊的MotionEvent,MotionEvent.ACTION_OUTSIDE
FLAG_SHOW_WHEN_LOCKED 使得window可以在锁屏状态下显示
FLAG_SHOW_WALLPAPER 如果你的window有透明的区域,墙纸会显示在那
FLAG_TURN_SCREEN_ON 当window被添加或者显示,系统会点亮屏幕
FLAG_DISMISS_KEYGUARD 当使用的是无密码的锁屏界面,显示此window会使锁屏界面被自动解锁
FLAG_SPLIT_TOUCH window会接收来自window边界之外发送给其他window的点击事件
FLAG_HARDWARE_ACCELERATED window是否启动硬件加速,请求硬件加速但不能保证硬件加速生效
FLAG_LOCAL_FOCUS_MODE 在这种模式下,window不会通过windowmanager获取到event
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS window负责绘制状态栏的背景

创建悬浮窗需要系统权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

3. 悬浮窗禁用

在Android6.0以后,悬浮窗权限默认是禁用的,需要用户确定打开,在返回时确认权限。

public void requestPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && !Settings.canDrawOverlays(this)) {
        Toast.makeText(this, "请授权!", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, REQUEST_OVERLAY_PERMISSION);
    } else {
        showSuspensionWindow(mSuspensionView);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_OVERLAY_PERMISSION) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {
            showSuspensionWindow(mSuspensionView);
        }
    }
}

源码下载: https://github.com/nai-chen/AndroidBlog

参考资料: https://blog.csdn.net/yhaolpz/article/details/68936932
参考资料: https://blog.csdn.net/core_ice/article/details/52464125

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340