private final WindowManager mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
// 2
mWindowManager.addView(mNavigationView, createLayoutParams(gravity));
// 3
private static WindowManager.LayoutParams createLayoutParams(int gravity) {
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
0);
layoutParams.gravity = gravity;
return layoutParams;
}
// 4
public LayoutParams(int w, int h, int _type, int _flags, int _format) {
super(w, h);
type = _type;
flags = _flags;
format = _format;
}
Flags
参数表示Window的属性,它有很多选项,通过这些选项可以控制Window的显示特性
属性值 |
描述 |
FLAG_NOT_FOCUSABLE |
表示Window不需要获取焦点,也不需要接收各种输入事件,此标记会同时启动FLAG_NOT_TOUCH_MODEL,最终事件会传递给下层的具有焦点的Window。 |
FLAG_NOT_TOUCH_MODAL |
表示系统会将当前Window区域以外的单击事件传递给底层的Window,而区域以内的单击事件则自己处理。一般都需要开启此标记,否则其他Window将无法收到单击事件。 |
FLAG_SHOW_WHEN_LOCKED |
表示Window可显示在锁屏界面。 |
// 只要窗口可见,就允许在开启状态的屏幕上锁屏.
public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
//窗口不能获得输入焦点,设置该标志的同时,FLAG_NOT_TOUCH_MODAL也会被设置
public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
//窗口不接收任何触摸事件
public static final int FLAG_NOT_TOUCHABLE = 0x00000010;
//在该窗口区域外的触摸事件传递给其他的Window,而自己只会处理窗口区域内的触摸事件
public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
//只要窗口可见,屏幕就会一直亮着
public static final int FLAG_KEEP_SCREEN_ON = 0x00000080;
//允许窗口超过屏幕之外
public static final int FLAG_LAYOUT_NO_LIMITS = 0x00000200;
//隐藏所有的屏幕装饰窗口,比如在游戏、播放器中的全屏显示
public static final int FLAG_FULLSCREEN = 0x00000400;
//窗口可以在锁屏的窗口之上显示
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
//当用户的脸贴近屏幕时(比如打电话),不会去响应此事件
public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;
//窗口显示时将屏幕点亮
public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
设置Window的Flag有三种方法
//1
Window mWindow =getWindow();
mWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
//2
Window mWindow =getWindow();
mWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//3
WindowManager.LayoutParams mWindowLayoutParams = new WindowManager.LayoutParams();
mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN;
WindowManager mWindowManager =(WindowManager)getSystemService(Context.WINDOW_SERVICE);
TextView mTextView=new TextView(this);
mWindowManager.addView(mTextView, mWindowLayoutParams);
Types
Type参数表示Window的类型,Window有三种类型,分别是应用Window、子Window和系统Window。Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖在层级小的Window的上面。这些层级范围对应着WindowManager.LayoutParams的type参数。想要Window位于所有Window的最顶层,那么采用较大的层级即可。
window |
层级 |
描述 |
应用Window |
0-99 |
对应一个Activity |
子Window |
1000~1999 |
不能单独存在,需附属特定的父Window。如Dialog |
系统Window |
2000~2999 |
需申明权限(SYSTEM_ALERT_WINDOW)才能创建。如Toast和状态栏 |
public static final int FIRST_APPLICATION_WINDOW = 1;//应用程序窗口类型初始值
public static final int TYPE_BASE_APPLICATION = 1;//窗口的基础值,其他的窗口值要大于这个值
public static final int TYPE_APPLICATION = 2;//普通的应用程序窗口类型
public static final int TYPE_APPLICATION_STARTING = 3;//应用程序启动窗口类型,用于系统在应用程序窗口启动前显示的窗口。
public static final int TYPE_DRAWN_APPLICATION = 4;
public static final int LAST_APPLICATION_WINDOW = 99;//应用程序窗口类型结束值
public static final int FIRST_SUB_WINDOW = 1000;//子窗口类型初始值
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4;
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
public static final int LAST_SUB_WINDOW = 1999;//子窗口类型结束值
public static final int FIRST_SYSTEM_WINDOW = 2000;//系统窗口类型初始值
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;//系统状态栏窗口
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;//搜索条窗口
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;//通话窗口
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;//系统ALERT窗口
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;//锁屏窗口
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;//TOAST窗口
...
public static final int LAST_SYSTEM_WINDOW = 2999;//系统窗口类型结束值
Z-order
当一个进程向WMS申请一个窗口时,WMS会为窗口确定显示次序。 为了方便窗口显示次序的管理,手机屏幕可以虚拟地用 X 、 Y 、 Z 轴来表示,其中 Z 轴垂直于屏幕,从屏幕内指向屏幕外,这样确定窗 口显示次序也就是确定窗口在 Z 轴上的次序,这个次序称为Z-Oder。 Type值是Z-Oder排序的依据,我们知道应用程序窗口的Type值范围为1 ~99,子窗口1000~1999,系统窗口2000~2999,在一般情况下, Type值越大则Z-Oder排序越靠前,就越靠近用户。当然窗口显示次序的逻辑不会这么简单,情况会比较多,举个常见的情况:当多个窗口 的Type值都是TYPE_APPLICATION,这时WMS会结合各种情况给出最终的 Z-Oder。
Activity的Window创建过程
① 入口在ActivityThread::performLaunchActivity → Activity::attach()
final void attach() {
//创建PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
//设置Callback
mWindow.setCallback(this);
//设置WindowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
}
Window:: setWindowManager
public void setWindowManager() {
// 1
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
// 2
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
WindowManagerImpl::createLocalWindowManager
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
createLocalWindowManager 方 法 同 样 也 是 创 建 WindowManagerImpl,不同的是这次创建WindowManagerImpl 时将创建它的 Window(PhoneWindow) 作为参数传了进来,这样 WindowManagerImpl就持有了 PhoneWindow的引用,可以对PhoneWindow进行操作,比如在PhoneWindow中添加View, 会调用WindowManagerImpl的addView方法。
WindowManagerImpl 虽然是WindowManager 的实现类,但是没有实现什么功能,而是将功能实现委托给了WindowManagerGlobal,这里用到的是桥接模式。
②:DecorView添加到PhoneWindow Activity::setContentView
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
DecorView是Activity中的顶级View,一般来说它的内部包含标题栏和内部栏,但是这个会随着主题的变换而发生改变。不管怎么样,内容栏是一定要存在的,并且内容来具体固定的id,那就是“content”,它的完整id是android.R.id.content。到这里为止DecorView已经被创建并初始化完毕,Activity的布局文件也已经成功添加到了DecorView的mContentParent中,但是这个时候DecorView还没有被WindowManager正式添加到Window中。
在ActivityThread的handleResumeActivity方法中,首先会调用Activity的onResume方法,接着会调用Activity的makeVisible(),正是在makeVisible方法中,DecorView真正地完成了添加和显示这两个过程,到这里Activity的视图才能被用户看到 。到这里,Activity的DecorView算是添加到了WindowManager中
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
阶段性总结
Window是抽象类,具体实现类为PhoneWindow,它对View进行管理。WindowManager是接口类,继承自接口ViewManager,用来管理Window的,实现类为WindowManagerImpl。如果想对Window(View)进行添加、更新和删除操作使用WindowManager,WindowManager会将具体的工作交由WMS来处理,WindowManager和WMS通过Binder来进行跨进程通信。
任玉刚 Android开发艺术探索
刘望舒 Android 进阶解密
相关推荐
我们先来深入理解Window和WindowManager的相关知识点。 1. **WindowManager接口与实现**: Android提供了`WindowManager`接口,用于操作窗口。然而,真正实现`WindowManager`功能的是`WindowManagerGlobal`类,它...
Window是一个抽象类,具体实现是 PhoneWindow 。不管是 Activity 、 Dialog 、 Toast 它们的视图都是附加在Window上的,因此Window实际上是View的直接管理者。
WindowManager则是与Window交互的接口,它允许开发者添加、更新和移除Window。 WindowManagerService是管理所有Window的核心服务,它负责处理Window的生命周期和布局。当通过WindowManager添加一个新的Window时,...
理解Window和WindowManager的工作原理对于深入Android应用开发至关重要。本文将详细探讨这两个概念及其相互关系。 首先,我们来解析“Window”。在Android中,窗口并不是直接与用户交互的对象,而是视图(View)的...
第8章 理解Window和WindowManager 294 8.1 Window和WindowManager 294 8.2 Window的内部机制 297 8.2.1 Window的添加过程 298 8.2.2 Window的删除过程 301 8.2.3 Window的更新过程 303 8.3 Window的创建过程 ...
第8章 理解Window和WindowManager / 294 8.1 Window和WindowManager / 294 8.2 Window的内部机制 / 297 8.2.1 Window的添加过程 / 298 8.2.2 Window的删除过程 / 301 8.2.3 Window的更新过程 / 303 ...
- **WindowManager**:负责管理Window的添加、删除和更新,Window是应用程序界面的基础。 - **Window创建过程**:了解Activity、Dialog、Toast创建Window的过程。 9. **四大组件的工作过程** - **Activity和服务...
Android悬浮窗实现原理和WindowManager详解 Android悬浮窗是指在Android系统中,可以悬浮在屏幕上的一种窗口,常见于QQ视频、...通过使用WindowManager和悬浮窗权限,可以实现悬浮窗的效果,提供了非常实用的功能。
Android 中 Window 管理深入讲解 Android 中的 Window 管理是 Android 开发中非常重要...Android 中的 Window 管理是非常复杂的,需要深入理解 Window 和 WindowManager 的关系,以及 Window 的 flags 等属性的使用。
总的来说,使用WindowManager和Service创建弹窗是一种高级的Android编程技巧,可以为用户提供非传统界面交互体验。但需要注意的是,这种做法需要谨慎处理权限和用户体验问题,避免对系统造成干扰或者滥用权限。
Actual Window Manager能够在一个包含你的任何窗口操作的特别的日志文件中保留记录,无论自动(如你窗口设置的配置那样),还是手动(用标题按钮,窗口菜单命令或热键),并自动定期发送此消息到Actual Tools这将帮助...
android13 WindowManager-Shell.jar
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); ``` 2. 创建LayoutParams对象:这将定义对话框在屏幕上的位置和属性。例如,可以使用LayoutParams.TYPE_SYSTEM_ALERT来...
本文将深入探讨Android中Window添加View的底层原理,包括Window和WindowManager的概念、交互方式以及添加View的关键步骤。 首先,Window是一个抽象类,实际的实现是PhoneWindow。创建Window并不直接操作,而是通过...
- 使用`WindowManager`服务,通常在`Service`或`Activity`中初始化`WindowManager`实例:`WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);` - 创建一个`LayoutParam`对象,定义...
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup....
`WindowManager`是Android系统服务之一,它允许应用管理窗口并控制它们在屏幕上的位置和显示方式。本篇将深入探讨如何利用`WindowManager`来创建一个悬浮窗(Floating Window)的demo。 首先,悬浮窗的本质是在应用...