zoukankan      html  css  js  c++  java
  • UIWindow的一点儿思考

    转自:http://www.cnblogs.com/smileEvday/archive/2012/11/16/UIWindow.html

      每一个IOS程序都有一个UIWindow,在我们通过模板简历工程的时候,xcode会自动帮我们生成一个window,然后让它变成keyWindow并显示出来。这一切都来的那么自然,以至于我们大部分时候都忽略了自己也是可以创建UIWindow对象。

      通常在我们需要自定义UIAlertView的时候(IOS 5.0以前AlertView的背景样式等都不能换)我们可以使用UIWindow来实现(设置windowLevel为Alert级别),网上有很多例子,这里就不详细说了。

      我的上一篇文章UIWindowLevel详解,中讲到了关于Windowlevel的东西,当时还只是看了看文档,知道有这么一回儿事。今天刚好遇到这块儿的问题,就顺便仔细看了一下UIWindow方面的东西,主要包括:WindowLevel以及keyWindow两个方面。

    一、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的确存在。

    复制代码
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert View"
                                                            message:@"Hello Wolrd, i'm AlertView!!!"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:@"Cancel", nil];
        [alertView show];
        [alertView release];
        
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"ActionSheet"
                                                                 delegate:nil
                                                        cancelButtonTitle:@"Cancel"
                                                   destructiveButtonTitle:@"Don't do that!"
                                                        otherButtonTitles:@"Hello Wolrd", nil];
        [actionSheet showInView:self.view];
        [actionSheet release];
    复制代码

      下面是程序运行截图:

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

    二、KeyWindow

      什么是keyWindow,官方文档中是这样解释的"The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window." 翻译过来就是说,keyWindow是指定的用来接收键盘以及非触摸类的消息,而且程序中每一个时刻只能有一个window是keyWindow。

      下面我们写个简单的例子看看非keyWindow能不能接受键盘消息和触摸消息,程序中我们在view中添加一个UITextField,然后新建一个alert级别的window,然后通过makeKeyAndVisible让它变成keyWindow并显示出来。代码如下:

    复制代码
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
        // Override point for customization after application launch.
        self.viewController = [[[SvUIWindowViewController alloc] initWithNibName:@"SvUIWindowViewController" bundle:nil] autorelease];
        self.window.rootViewController = self.viewController;
        [self.window makeKeyAndVisible];
        
        UIWindow *window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 80, 320, 320)];
        window1.backgroundColor = [UIColor redColor];
        window1.windowLevel = UIWindowLevelAlert;
        [window1 makeKeyAndVisible];
    
        return YES;
    }
    复制代码
    复制代码
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        [self registerObserver];
        
        // add a textfield
        UITextField *filed = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 60)];
        filed.placeholder = @"Input something here";
        filed.clearsOnBeginEditing = YES;
        filed.borderStyle = UITextBorderStyleRoundedRect;
        [self.view addSubview:filed];
        [filed release];
    }
    复制代码

      运行截图如下:

      从图中可以看出,虽然我们自己新建了一个然后设置为keyWindow并显示,但是点击程序中默认window上添加的textField还是可以唤出键盘,而且还可以正常接受键盘输入,只是键盘被挡住了,说明非keyWindow也是可以接受键盘消息,这一点和文档上说的不太一样。

      观察UIWindow的文档,我们可以发现里面有四个关于window变化的通知:

      UIWindowDidBecomeVisibleNotification

      UIWindowDidBecomeHiddenNotification

      UIWindowDidBecomeKeyNotification

      UIWindowDidResignKeyNotification

      这四个通知对象中的object都代表当前已显示(隐藏),已变成keyWindow(非keyWindow)的window对象,其中的userInfo则是空的。于是我们可以注册这个四个消息,再打印信息来观察keyWindow的变化以及window的显示,隐藏的变动。

      代码如下:

    SvUIWindowViewController.m

      a、当我们打开viewDidAppear中“[self presentAlertView];”的时候,控制台输出如下

      根据打印的信息我们可以看出流程如下:

      1、程序默认的window先显示出来

      2、默认的window再变成keyWindow

      3、AlertView的window显示出来

      4、默认的window变成非keyWindow

      5、最终AlertView的window变成keyWindow

      总体来说就是“要想当老大(keyWindow),先从小弟(非keyWindow)开始混起” 而且根据打印的信息我们同事可以知道默认的window的level是0,即normal级别;AlertView的window的level是1996,比Alert级别稍微低了一点儿。

      b、当我们打开viewDidAppear中“[self presentActionSheet];”的时候,控制台输出如下:  

      keyWindow的变化和window的显示和上面的流程一样,同时我们可以看出ActionSheet的window的level是2001。

      c、接着上一步,我们点击弹出ActionSheet的cancel的时候,控制台输出如下:

      我们看出流程如下:

      1、首先ActionSheet的window变成非keyWindow

      2、程序默认的window变成keyWindow

      3、ActionSheet的window在隐藏掉

      总体就是“想隐居幕后可以,但得先交出权利”。

     

  • 相关阅读:
    Visual Studio使用技巧
    排颜色问题——数组 leetcode lintcode
    【简洁】微信为何总令人感觉如此简洁、?(一)
    字符串通信协议解析函数
    我所改造的JSocket适用于任何DELPHI版本
    缓存和字符串相互转换
    TcxDBTreeList导出EXCEL
    TcxGrid导出EXCEL
    TdxAlertWindowManager右下角HINT显示控件
    好用的编辑框布局控件TdxLayoutControl
  • 原文地址:https://www.cnblogs.com/wangpei/p/3538679.html
Copyright © 2011-2022 走看看