配色: 字号:
详解iOS设计中的UIWindow使用
2016-12-09 | 阅:  转:  |  分享 
  
详解iOS设计中的UIWindow使用

这篇文章主要介绍了iOS设计中的UIWindow使用,包括UIWindowLevel和KeyWindow两个大的方面的讲解,需要的朋友可以参考下

每一个IOS程序都有一个UIWindow,在我们通过模板简历工程的时候,xcode会自动帮我们生成一个window,然后让它变成keyWindow并显示出来。这一切都来的那么自然,以至于我们大部分时候都忽略了自己也是可以创建UIWindow对象。通常在我们需要自定义UIAlertView的时候(IOS5.0以前AlertView的背景样式等都不能换)我们可以使用UIWindow来实现(设置windowLevel为Alert级别),网上有很多例子,这里就不详细说了。一、UIWindowLevel我们都知道UIWindow有三个层级,分别是Normal,StatusBar,Alert。打印输出他们三个这三个层级的值我们发现从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中等水平,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别上的,系统顶部的状态栏应该是处于StatusBar级别,UIActionSheet和UIAlertView这些通常都是用来中断正常流程,提醒用户等操作,因此位于Alert级别。上一篇文章中我也提到了一个猜想,既然三个级别的值之间相差1000,而且我们细心的话查看UIWindow的头文件就会发现有一个实例变量_windowSublevel,那我们就可以定义很多中间级别的Window。例如可以自定义比系统UIAlertView级别低一点儿的window。于是写了一个小demo,通过打印发现系统的UIAlertView的级别是1996,而与此同时UIActionSheet的级别是2001,这样也验证了subLevel的确存在。

复制代码代码如下:

UIAlertViewalertView=[[UIAlertViewalloc]initWithTitle:@"AlertView"message:@"HelloWolrd,i''mAlertView!!!"delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:@"Cancel",nil];[alertViewshow];[alertViewrelease];UIActionSheetactionSheet=[[UIActionSheetalloc]initWithTitle:@"ActionSheet"delegate:nilcancelButtonTitle:@"Cancel"destructiveButtonTitle:@"Don''tdothat!"otherButtonTitles:@"HelloWolrd",nil];[actionSheetshowInView:self.view];[actionSheetrelease];

下面是程序运行截图:

根据window显示级别优先的原则,级别高的会显示在上面,级别低的在下面,我们程序正常显示的view位于最底层,至于具体怎样获取UIAlertView和UIActionSheet的level,我会在下面第二部分keyWindow中介绍并给出相应的代码。

UIWindow在显示的时候会根据UIWindowLevel进行排序的,即Level高的将排在所有Level比他低的层级的前面。下面我们来看UIWindowLevel的定义:

复制代码代码如下:

constUIWindowLevelUIWindowLevelNormal;

constUIWindowLevelUIWindowLevelAlert;

constUIWindowLevelUIWindowLevelStatusBar;



typedefCGFloatUIWindowLevel;IOS系统中定义了三个window层级,其中每一个层级又可以分好多子层级(从UIWindow的头文件中可以看到成员变量CGFloat_windowSublevel;),不过系统并没有把则个属性开出来。UIWindow的默认级别是UIWindowLevelNormal,我们打印输出这三个level的值分别如下:

1

2

3

4

5 2012-03-2722:46:08.752UIViewSample[395:f803]Normalwindowlevel:0.000000

2012-03-2722:46:08.754UIViewSample[395:f803]Alertwindowlevel:2000.000000

2012-03-2722:46:08.755UIViewSample[395:f803]Statuswindowlevel:1000.000000 这样印证了他们级别的高低顺序从小到大为Normal
复制代码代码如下:

-(BOOL)application:(UIApplication)applicationdidFinishLaunchingWithOptions:(NSDictionary)launchOptions{self.window=[[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]]autorelease];self.window.backgroundColor=[UIColoryellowColor];[self.windowmakeKeyAndVisible];UIWindownormalWindow=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];normalWindow.backgroundColor=[UIColorblueColor];normalWindow.windowLevel=UIWindowLevelNormal;[normalWindowmakeKeyAndVisible];CGRectwindowRect=CGRectMake(50,50,[[UIScreenmainScreen]bounds].size.width-100,[[UIScreenmainScreen]bounds].size.height-100);UIWindowalertLevelWindow=[[UIWindowalloc]initWithFrame:windowRect];alertLevelWindow.windowLevel=UIWindowLevelAlert;alertLevelWindow.backgroundColor=[UIColorredColor];[alertLevelWindowmakeKeyAndVisible];UIWindowstatusLevelWindow=[[UIWindowalloc]initWithFrame:CGRectMake(0,50,320,20)];statusLevelWindow.windowLevel=UIWindowLevelStatusBar;statusLevelWindow.backgroundColor=[UIColorblackColor];[statusLevelWindowmakeKeyAndVisible];NSLog(@"Normalwindowlevel:%f",UIWindowLevelNormal);NSLog(@"Alertwindowlevel:%f",UIWindowLevelAlert);NSLog(@"Statuswindowlevel:%f",UIWindowLevelStatusBar);returnYES;}

运行结果如下图:我们可以注意到两点:1)我们生成的normalWindow虽然是在第一个默认的window之后调用makeKeyAndVisible,但是仍然没有显示出来。这说明当Level层级相同的时候,只有第一个设置为KeyWindow的显示出来,后面同级的再设置KeyWindow也不会显示。2)statusLevelWindow在alertLevelWindow之后调用makeKeyAndVisible,仍然只是显示在alertLevelWindow的下方。这说明UIWindow在显示的时候是不管KeyWindow是谁,都是Level优先的,即Level最高的始终显示在最前面。

二、KeyWindow什么是keyWindow,官方文档中是这样解释的"Thekeywindowistheonethatisdesignatedtoreceivekeyboardandothernon-touchrelatedevents.Onlyonewindowatatimemaybethekeywindow."翻译过来就是说,keyWindow是指定的用来接收键盘以及非触摸类的消息,而且程序中每一个时刻只能有一个window是keyWindow。下面我们写个简单的例子看看非keyWindow能不能接受键盘消息和触摸消息,程序中我们在view中添加一个UITextField,然后新建一个alert级别的window,然后通过makeKeyAndVisible让它变成keyWindow并显示出来。代码如下:

复制代码代码如下:

-(BOOL)application:(UIApplication)applicationdidFinishLaunchingWithOptions:(NSDictionary)launchOptions{self.window=[[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]]autorelease];//Overridepointforcustomizationafterapplicationlaunch.self.viewController=[[[SvUIWindowViewControlleralloc]initWithNibName:@"SvUIWindowViewController"bundle:nil]autorelease];self.window.rootViewController=self.www.hunanwang.netviewController;[self.windowmakeKeyAndVisible];UIWindowwindow1=[[UIWindowalloc]initWithFrame:CGRectMake(0,80,320,320)];window1.backgroundColor=[UIColorredColor];window1.windowLevel=UIWindowLevelAlert;[window1makeKeyAndVisible];

returnYES;}

复制代码代码如下:

-(void)viewDidLoad{[superviewDidLoad];//Doanyadditionalsetupafterloadingtheview,typicallyfromanib.[selfregisterObserver];//addatextfieldUITextFieldfiled=[[UITextFieldalloc]initWithFrame:CGRectMake(0,0,320,60)];filed.placeholder=@"Inputsomewww.visa158.comthinghere";filed.clearsOnBeginEditing=YES;filed.borderStyle=UITextBorderStyleRoundedRect;[self.viewaddSubview:filed];[filedrelease];}

运行截图如下:从图中可以看出,虽然我们自己新建了一个然后设置为keyWindow并显示,但是点击程序中默认window上添加的textField还是可以唤出键盘,而且还可以正常接受键盘输入,只是键盘被挡住了,说明非keyWindow也是可以接受键盘消息,这一点和文档上说的不太一样。观察UIWindow的文档,我们可以发现里面有四个关于window变化的通知:

1

2

3

4

5

6

7 UIWindowDidBecomeVisibleNotification

UIWindowDidBecomeHiddenNotification

UIWindowDidBecomeKeyNotification

UIWindowDidResignKeyNotification 根据打印的信息我们可以看出流程如下:1、程序默认的window先显示出来2、默认的window再变成keyWindow3、AlertView的window显示出来4、默认的window变成非keyWindow5、最终AlertView的window变成keyWindow总体来说就是“要想当老大(keyWindow),先从小弟(非keyWindow)开始混起”而且根据打印的信息我们同事可以知道默认的window的level是0,即normal级别;AlertView的window的level是1996,比Alert级别稍微低了一点儿。b、当我们打开viewDidAppear中“[selfpresentActionSheet];”的时候,控制台输出如下:



keyWindow的变化和window的显示和上面的流程一样,同时我们可以看出ActionSheet的window的level是2001。c、接着上一步,我们点击弹出ActionSheet的cancel的时候,控制台输出如下:

我们看出流程如下:1、首先ActionSheet的window变成非keyWindow2、程序默认的window变成keyWindow3、ActionSheet的window在隐藏掉总体就是“想隐居幕后可以,但得先交出权利”。























献花(0)
+1
(本文系白狐一梦首藏)