`
luochuang
  • 浏览: 24045 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

window和windowmanager

 
阅读更多
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,这里用到的是桥接模式。

 

 Vm9PsI.png

 ②: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和windowManager1

    我们先来深入理解Window和WindowManager的相关知识点。 1. **WindowManager接口与实现**: Android提供了`WindowManager`接口,用于操作窗口。然而,真正实现`WindowManager`功能的是`WindowManagerGlobal`类,它...

    理解Window和WindowManager

    Window是一个抽象类,具体实现是 PhoneWindow 。不管是 Activity 、 Dialog 、 Toast 它们的视图都是附加在Window上的,因此Window实际上是View的直接管理者。

    深入理解Android中的Window和WindowManager

    WindowManager则是与Window交互的接口,它允许开发者添加、更新和移除Window。 WindowManagerService是管理所有Window的核心服务,它负责处理Window的生命周期和布局。当通过WindowManager添加一个新的Window时,...

    windowmanager

    理解Window和WindowManager的工作原理对于深入Android应用开发至关重要。本文将详细探讨这两个概念及其相互关系。 首先,我们来解析“Window”。在Android中,窗口并不是直接与用户交互的对象,而是视图(View)的...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    第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的创建过程 ...

    Android开发艺术探索

     第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  ...

    Android开发艺术探索1

    - **WindowManager**:负责管理Window的添加、删除和更新,Window是应用程序界面的基础。 - **Window创建过程**:了解Activity、Dialog、Toast创建Window的过程。 9. **四大组件的工作过程** - **Activity和服务...

    Android利用WindowManager实现悬浮窗

    Android悬浮窗实现原理和WindowManager详解 Android悬浮窗是指在Android系统中,可以悬浮在屏幕上的一种窗口,常见于QQ视频、...通过使用WindowManager和悬浮窗权限,可以实现悬浮窗的效果,提供了非常实用的功能。

    Android中Window的管理深入讲解

    Android 中 Window 管理深入讲解 Android 中的 Window 管理是 Android 开发中非常重要...Android 中的 Window 管理是非常复杂的,需要深入理解 Window 和 WindowManager 的关系,以及 Window 的 flags 等属性的使用。

    WindowManager弹窗

    总的来说,使用WindowManager和Service创建弹窗是一种高级的Android编程技巧,可以为用户提供非传统界面交互体验。但需要注意的是,这种做法需要谨慎处理权限和用户体验问题,避免对系统造成干扰或者滥用权限。

    android13 WindowManager-Shell.jar

    android13 WindowManager-Shell.jar

    windowmanager对话框

    WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); ``` 2. 创建LayoutParams对象:这将定义对话框在屏幕上的位置和属性。例如,可以使用LayoutParams.TYPE_SYSTEM_ALERT来...

    Android中Window添加View的底层原理

    本文将深入探讨Android中Window添加View的底层原理,包括Window和WindowManager的概念、交互方式以及添加View的关键步骤。 首先,Window是一个抽象类,实际的实现是PhoneWindow。创建Window并不直接操作,而是通过...

    Actual Window Manager 8.2.2汉化破解版.rar

    Actual Window Manager能够在一个包含你的任何窗口操作的特别的日志文件中保留记录,无论自动(如你窗口设置的配置那样),还是手动(用标题按钮,窗口菜单命令或热键),并自动定期发送此消息到Actual Tools这将帮助...

    Android悬浮框权限判断WindowManager

    - 使用`WindowManager`服务,通常在`Service`或`Activity`中初始化`WindowManager`实例:`WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);` - 创建一个`LayoutParam`对象,定义...

    android 采用windowmanager屏蔽home键

    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup....

    Android 利用WindowManager实现悬浮窗 demo

    `WindowManager`是Android系统服务之一,它允许应用管理窗口并控制它们在屏幕上的位置和显示方式。本篇将深入探讨如何利用`WindowManager`来创建一个悬浮窗(Floating Window)的demo。 首先,悬浮窗的本质是在应用...

Global site tag (gtag.js) - Google Analytics