Android 7.1 GUI系统-窗口管理WMS-窗口属性(二)

窗口类型及属性。

1),Android都有那些窗口类型,定义在WindowManager.java的内部类LayoutParams中。

public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable @WindowManager.java{
//代表通常的应用程序窗口的开始。
	public static final int FIRST_APPLICATION_WINDOW = 1;
//应用窗口的基础值,其他应用窗口都在这之上。
	public static final int TYPE_BASE_APPLICATION   = 1;
//普通的应用窗口,它属于一个Activity token identifying。
	public static final int TYPE_APPLICATION        = 2;
//启动窗口,它不是被应用程序自身用的,而是被系统使用来显示某些东西,在应用程序能显示它自己的窗口之前。
	public static final int TYPE_APPLICATION_STARTING = 3;
//应用窗口的结束值。
	 public static final int LAST_APPLICATION_WINDOW = 99;

//子窗口的起始值,这类必须设置它依附的窗口,在Z-order上,子窗口的类型紧邻它依附的窗口,子窗口的坐标空间也是相对于它的依附窗口。
	public static final int FIRST_SUB_WINDOW = 1000;
//应用程序的panel窗口,比如hint窗口,pop窗口等,这类窗口在父窗口之上。
	public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
//显示多媒体的窗口,如Video,这类窗口在父窗口之下。
	public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
//应用的sub-panel窗口,显示在父窗口和TYPE_APPLICATION_PANEL之上。
	public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
//类似与TYPE_APPLICATION_PANEL,但是这个窗口的layout发生像顶层窗口,而不是向容器的子窗口。
	public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
//多媒体窗口的覆盖层,位于TYPE_APPLICATION_MEDIA 和应用窗口之间,通常是透明的才有意义。
	public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4;
//子窗口的结束值。
	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;
//alert窗口,通常在应用窗口之上。
	public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
//锁屏窗口。
	public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
//短暂的通知窗口。
	public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
//系统的overlay窗口,显示在一切之上,但是不能有input焦点,否则会妨碍keyguard。
	public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
//电话优先窗口,即使keyguard是active的,也会显示。
	public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
//从状态栏下拉出的panel,recentpanel。
	public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
//输入法窗口。
	public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;
//墙纸窗口,位于任何想在wallpaper之上的窗口后面。
	public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
//音量条窗口。
	public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
//屏保窗口,仅仅在keyguard之上。
	public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
//系统窗口的结束值。
	public static final int LAST_SYSTEM_WINDOW      = 2999;
}

当进程想WMS申请一个窗口时,要指定窗口类型,WMS会根据申请的窗口类型及当前系统中已有窗口的情况,分配层级值,层级越大的窗口越靠近用户。层级的分配规则主要由assignLayersLocked实现。


final void assignLayersLocked(WindowList windows)@WindowLayersController.java {
	int curBaseLayer = 0;
	int curLayer = 0;
//windows保存了当前系统中的所有窗口。
	for (int i = 0, windowCount = windows.size(); i < windowCount; i++) {
		final WindowState w = windows.get(i);
		boolean layerChanged = false;
		int oldLayer = w.mLayer;
		if (w.mBaseLayer == curBaseLayer || w.mIsImWindow || (i > 0 && w.mIsWallpaper)) {
//这个窗口的基础层级跟前一个窗口的基础层级一致,只要添加间隔WINDOW_LAYER_MULTIPLIER。这个间隔值是5。
			curLayer += WINDOW_LAYER_MULTIPLIER;
		}else{
//如果不一致,把 curBaseLayer设置为这个窗口的值。
			curBaseLayer = curLayer = w.mBaseLayer;
		}
	}
}

一个窗口的mBaseLayer的值是怎么来的呢?一个窗口有关的信息都是在WindowState中保存的。


WindowState(...WindowState attachedWindow,WindowManager.LayoutParams a,...)@WindowState.java{
	if ((mAttrs.type >= FIRST_SUB_WINDOW &&mAttrs.type <= LAST_SUB_WINDOW)) {
//如果子窗口,层级值取决于父窗口的类型,每种类型在窗口管理策略中有一个对照表,来确定基础层级值。
		mBaseLayer = mPolicy.windowTypeToLayerLw(attachedWindow.mAttrs.type)
			 *WindowManagerService.TYPE_LAYER_MULTIPLIER
			+ WindowManagerService.TYPE_LAYER_OFFSET;
//子窗口,还有一个相对父窗口的偏移值,这个偏移值决定了子窗口可能在父窗口之上,也可能在父窗口之下。
		mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
	}else{
//基础层级值还要乘上TYPE_LAYER_MULTIPLIER(10000),加上偏移 TYPE_LAYER_OFFSET(1000),因为系统中可能出现同类型的多个窗口,所以要有一个较大的间隔。
		mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
			* WindowManagerService.TYPE_LAYER_MULTIPLIER
			+ WindowManagerService.TYPE_LAYER_OFFSET;
	}
}

上面计算层级值时,用到mPolicy,就是窗口管理策略类的实例。Android手机系统,默认的窗口管理策略类是PhoneWindowManager,在WindowManagerService.java中直接实例化了相应对象。

finalWindowManagerPolicy mPolicy = new PhoneWindowManager();

所以WindowState构造函数中用到的两个函数windowTypeToLayerLwsubWindowTypeToLayerLw都是PhoneWindowManager中的方法。


public int windowTypeToLayerLw(int type)@PhoneWindowManager.java {
        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
            return 2;
        }
        switch (type) {
        case TYPE_PRIVATE_PRESENTATION:
            return 2;
        case TYPE_WALLPAPER:
            // wallpaper is at the bottom, though the window manager may move it.
            return 2;
        case TYPE_DOCK_DIVIDER:
            return 2;
        case TYPE_QS_DIALOG:
            return 2;
        case TYPE_PHONE:
            return 3;
        case TYPE_SEARCH_BAR:
        case TYPE_VOICE_INTERACTION_STARTING:
            return 4;
        case TYPE_VOICE_INTERACTION:
            // voice interaction layer is almost immediately above apps.
            return 5;
        case TYPE_INPUT_CONSUMER:
            return 6;
        case TYPE_SYSTEM_DIALOG:
            return 7;
        case TYPE_TOAST:
            // toasts and the plugged-in battery thing
            return 8;
        case TYPE_PRIORITY_PHONE:
            // SIM errors and unlock.  Not sure if this really should be in a high layer.
            return 9;
        case TYPE_DREAM:
            // used for Dreams (screensavers with TYPE_DREAM windows)
            return 10;
        case TYPE_SYSTEM_ALERT:
            // like the ANR / app crashed dialogs
            return 11;
        case TYPE_INPUT_METHOD:
            // on-screen keyboards and other such input method user interfaces go here.
            return 12;
        case TYPE_INPUT_METHOD_DIALOG:
            // on-screen keyboards and other such input method user interfaces go here.
            return 13;
        case TYPE_KEYGUARD_SCRIM:
            // the safety window that shows behind keyguard while keyguard is starting
            return 14;
        case TYPE_STATUS_BAR_SUB_PANEL:
            return 15;
        case TYPE_STATUS_BAR:
            return 16;
        case TYPE_STATUS_BAR_PANEL:
            return 17;
        case TYPE_KEYGUARD_DIALOG:
            return 18;
        case TYPE_VOLUME_OVERLAY:
            // the on-screen volume indicator and controller shown when the user
            // changes the device volume
            return 19;
        case TYPE_SYSTEM_OVERLAY:
            // the on-screen volume indicator and controller shown when the user
            // changes the device volume
            return 20;
        case TYPE_NAVIGATION_BAR:
            // the navigation bar, if available, shows atop most things
            return 21;
        case TYPE_NAVIGATION_BAR_PANEL:
            // some panels (e.g. search) need to show on top of the navigation bar
            return 22;
        case TYPE_SCREENSHOT:
            // screenshot selection layer shouldn't go above system error, but it should cover
            // navigation bars at the very least.
            return 23;
        case TYPE_SYSTEM_ERROR:
            // system-level error dialogs
            return 24;
        case TYPE_MAGNIFICATION_OVERLAY:
            // used to highlight the magnified portion of a display
            return 25;
        case TYPE_DISPLAY_OVERLAY:
            // used to simulate secondary display devices
            return 26;
        case TYPE_DRAG:
            // the drag layer: input for drag-and-drop is associated with this window,
            // which sits above all other focusable windows
            return 27;
        case TYPE_ACCESSIBILITY_OVERLAY:
            // overlay put by accessibility services to intercept user interaction
            return 28;
        case TYPE_SECURE_SYSTEM_OVERLAY:
            return 29;
        case TYPE_BOOT_PROGRESS:
            return 30;
        case TYPE_POINTER:
            // the (mouse) pointer layer
            return 31;
        }
        Log.e(TAG, "Unknown window type: " + type);
        return 2;
}

public int subWindowTypeToLayerLw(int type) @PhoneWindowManager.java{
        switch (type) {
        case TYPE_APPLICATION_PANEL:
        case TYPE_APPLICATION_ATTACHED_DIALOG:
            return APPLICATION_PANEL_SUBLAYER;
        case TYPE_APPLICATION_MEDIA:
            return APPLICATION_MEDIA_SUBLAYER;
        case TYPE_APPLICATION_MEDIA_OVERLAY:
            return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
        case TYPE_APPLICATION_SUB_PANEL:
            return APPLICATION_SUB_PANEL_SUBLAYER;
        case TYPE_APPLICATION_ABOVE_SUB_PANEL:
            return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
        }
        Log.e(TAG, "Unknown sub-window type: " + type);
        return 0;
    }


2),窗口都有那些属性。

窗口属性除了前面的窗口类型外,还有窗口标记,都是放置在WindowManager.LayoutParams中。


public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable @WindowManager.java{
//只要这个窗口是可见的,即使屏幕是开启的也允许锁屏,可以单独使用,也可以结合FLAG_KEEP_SCREEN_ON,或者
FLAG_SHOW_WHEN_LOCKED。
	public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001;
//在这个窗口背后的所有东西都会变暗,使用dimAmount控制变暗的程度。
	public static final int FLAG_DIM_BEHIND        = 0x00000002;
//这个窗口不获取按键输入焦点,所以不能把key或别的button事件给它,这些事件会发给它后面的窗口,这个标记会enable FLAG_NOT_TOUCH_MODAL。
	public static final int FLAG_NOT_FOCUSABLE      = 0x00000008;
//这个窗口不接收touch 事件。
	public static final int FLAG_NOT_TOUCHABLE      = 0x00000010;
//如果FLAG_NOT_FOCUSABLE没有设置,这个窗口是focusable的,允许这个窗口外的pointer事件发给它后面的窗口,如果这个窗口是not focusable的,它自己会处理所有的pointer事件。
	public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020;
//设置这个flag,如果设备睡眠了,你可以接收到第一次touch 事件,通常第一次的touch事件是被系统消费,因为用户看不到他们按到的是什么。
	public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
//只要窗口是可见的,就要设备保持屏幕是亮的。
	public static final int FLAG_KEEP_SCREEN_ON     = 0x00000080;
//让窗口在整个屏幕范围内,忽略边上的装饰条(如状态栏)。
	public static final int FLAG_LAYOUT_IN_SCREEN   = 0x00000100;
//允许窗口超过屏幕区域。
	public static final int FLAG_LAYOUT_NO_LIMITS   = 0x00000200;
//隐藏所有的屏幕装饰条,全屏的窗口会忽略SOFT_INPUT_ADJUST_RESIZE整个值,窗口依然保持全屏不会resize。
这个flag可以在主题中控制,如:android.R.attr#windowFullscreen,Theme_Black_NoTitleBar_Fullscreen。。。
	public static final int FLAG_FULLSCREEN      = 0x00000400;
//会覆盖掉FLAG_FULLSCREEN,强制显示屏幕装饰条。
	public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
//认为窗口的内容是受保护的,禁止出现在屏幕截图中,或者不安全的显示中。
	public static final int FLAG_SECURE             = 0x00002000;
//有时跟屏幕贴的很近,如打电话时,这种情况下的某些事件可能是无意的,不应该响应。
	public static final int FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000;
//窗口可以显示在锁屏窗口之上,结合FLAG_KEEP_SCREEN_ON,点亮屏幕时在显示锁屏窗口前,可以直接显示这个窗口;结合FLAG_DISMISS_KEYGUARD,可以自动退出非安全的锁屏。
	public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;	
//系统墙纸会显示在窗口后面,只有窗口surface是透明的区域才能看到后面的墙纸。可以通过主题控制,android.R.attr#windowShowWallpaper,android.R.style#Theme_Wallpaper_NoTitleBar...
	public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
//窗口显示时,点亮屏幕。
	public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
//窗口显示时,退出非安全锁屏。
	public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
//设置这个flag的窗口会接收它范围之外的touch事件,发送给支持多点触控的其他窗口。
	public static final int FLAG_SPLIT_TOUCH = 0x00800000;
//窗口是否需要硬件加速。可以通过编程的方式控制,比如:
Window w = activity.getWindow();
in Activity's onCreate();
w.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
	WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
这个flag的设置要在setContentView之前。
如果在manifest中用android.R.attr#hardwareAccelerated打开了硬件加速,上面的方法不能disable。
这个flag在activity和应用的xml属性中,是被系统默认enable的,在manifest把它disable,就可以在Activity或者dialog中通过上面的方法enable或者disable。
	public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000;
//允许窗口的内容超出屏幕的overscan区域,窗口应该正确的调整它的内容来适应overscan区域。
这个flag也可以在主题中控制,android.R.attr#windowOverscan,android.R.style#Theme_Holo_NoActionBar_Overscan…
设置这个flag的窗口,正常的内容出现在overscan区域可能会有一定程度的模糊,为了确保内容的关键部分可以对用户可见,可以使用View.setFitsSystemWindows(boolean),设置view层次中一些点有适当的偏移量。
类似的方法属性有:android.R.attr#fitsSystemWindows,View.fitSystemWindows(Rect),View.setSystemUiVisibility(int)...
	public static final int FLAG_LAYOUT_IN_OVERSCAN = 0x02000000;
//设置透明的状态栏,可以在主题中通过属性控制:android.R.attr#windowTranslucentStatus,android.R.style#Theme_Holo_NoActionBar_TranslucentDecor…
设置这个flag的窗口,会自动设置View#SYSTEM_UI_FLAG_LAYOUT_STABLE,View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
	public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
//使窗口置于本地焦点模式,这个模式下的窗口可以使用Window#setLocalFocus(boolean, boolean),控制焦点独立于windowmanager,通常这个模式下的窗口不会从WindowManager得到touch,key事件,而是仅仅通过本地injection(Window#injectInputEvent(InputEvent)).
	public static final int FLAG_LOCAL_FOCUS_MODE = 0x10000000;
}

窗口标记的设置方法:

Windoww = activity.getWindow();

w.setFlags(W,indowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,

WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);


3),除了WindowManager.LayoutParams中的属性外,View.java中的一些Flag也会影响窗口的显示,如SystemUI相关的。


public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource @View.java{
//setSystemUiVisibility(int),view请求systemUI可见。
	public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
//View请求systemUI进入低调模式,通常用于games,book readers,video plahers,或者其他身临其境的应用,这个模式下,状态栏或者导航图标会变暗。
	public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
//View请求进入普通的全屏模式,以便在用户跟应用交互时,它的内容可以占据整个屏幕。
这个flag跟WindowManager.LayoutParams.FLAG_FULLSCREEN有相同的视觉效果,在这中模式下的view 窗口,非关键性的屏幕装饰都会被隐藏,如果通过Window.FEATURE_ACTION_BAR_OVERLAY让ActionBar处于overlay模式,SYSTEM_UI_FLAG_FULLSCREEN这个flag也会隐藏actionbar。
如果需要长时间的全屏,使用WindowManager.LayoutParams#FLAG_FULLSCREEN是较好的选择,如果是短暂的全屏可以使用SYSTEM_UI_FLAG_FULLSCREEN。
	public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;

	public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
	public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
	public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
	public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
	public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
...
}

可以通过setSystemUiVisibility(int)设置一个View的属性,如果要设置整个Viewtree的属性,可以在ActivityonCreate中,setContentView之前,通过以下代码设置:

intviewFlag = View.SYSTEM_UI_FLAG_FULLSCREEN |SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

|SYSTEM_UI_FLAG_LAYOUT_STABLE;

getWindow(),getDecorView().setSystemUiVisibility(viewFlag);


C#开发,可解析WMS服务,并进行浏览,功能强大,GIS开发人员可参考文件列表 Get Capabilities Example ........................\AssemblyInfo.cs ........................\Get Capabilities Example.csproj ........................\GetCapabilitiesExample.cs Get Map Asynch Example ......................\AssemblyInfo.cs ......................\Get Map Asynch Example.csproj ......................\GetMapAsynchExample.cs ......................\GetMapAsynchExample.resx Get Map Example ...............\AssemblyInfo.cs ...............\Get Map Example.csproj ...............\GetMapExample.cs GLOBECapabilities20040423.xml MapAnimation ............\AssemblyInfo.cs ............\Map Animation.csproj ............\MapAnimation.cs ............\MapAnimation.resx WMS Overview Article.html WMS Overview.sln Wms.Client ..........\AssemblyInfo.cs ..........\Capabilities.cs ..........\CLSDFOLD.BMP ..........\DefaultServerDescriptors.xml ..........\DownloadCache.cs ..........\ENTIRNET.BMP ..........\ENTIRNETX.bmp ..........\ENTIRNETX.ICO ..........\ExtensionMap.cs ..........\Layer.cs ..........\OPENFOLD.BMP ..........\PreviewDialog.cs ..........\PreviewDialog.resx ..........\RequestBuilder.cs ..........\Retriever.cs ..........\Server.cs ..........\ServerAddDialog.cs ..........\ServerAddDialog.resx ..........\ServerDescriptor.cs ..........\Wms.Client.csproj ..........\WmsDialog.cs ..........\WmsDialog.resx ..........\WmsException.cs ..........\WmsServerDescriptors.cs ..........\WmsServerDescriptors.xsd WMSBrowser ..........\AssemblyInfo.cs ..........\MapForm.cs ..........\MapForm.resx ..........\WMSBrowser.cs ..........\WMSBrowser.csproj ..........\WMSBrowser.resx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值