iOS UIWindow 覆盖 StatusBar

栏目: IOS · 发布时间: 6年前

内容简介:最近产品要做一个消息的通知,而且通知是覆盖在 StatusBar 上面的。如果是普通的 UIView 则肯定是不行的,因为 StatusBar 为系统全局性的视图,所以要想覆盖它,则必须为 Statusbar 类型的,那么也就是 UIWindow 了。window等级,即window在z轴上的层级关系,默认是0。UIWindowLevel 本身是一个 CGFloat 类型,可以随意设置或进行加减,高等级会显示在低等级上面。系统给出了三种常用等级:这样创建的与 statusbar 大小一样的UIWindow

最近产品要做一个消息的通知,而且通知是覆盖在 StatusBar 上面的。如果是普通的 UIView 则肯定是不行的,因为 StatusBar 为系统全局性的视图,所以要想覆盖它,则必须为 Statusbar 类型的,那么也就是 UIWindow 了。

UIWindow 的基础介绍

  • UIWindow是一种特殊的UIView,通常在一个app中至少会有一个UIWindow。
  • iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就显示在屏幕上了。
  • 一个iOS程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow就看不到任何UI界面。
  • 状态栏和键盘都是特殊的UIWindow。

这里有三个重要的对象UIScreen,UIWindow,UIView。

  1. UIScreen对象识别物理屏幕连接到设备
  2. UIWindow对象提供绘画支持给屏幕
  3. UIView执行绘画,当窗口要显示内容的时候,UIView绘画出他们的内容并附加到窗口上。

UIWindow 等级

window等级,即window在z轴上的层级关系,默认是0。UIWindowLevel 本身是一个 CGFloat 类型,可以随意设置或进行加减,高等级会显示在低等级上面。系统给出了三种常用等级:

UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal;      0
UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert;       2000
UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar;   4000

初始化 UIWindow 覆盖 StatusBar

-(void)initWindow {
  //初始化statusView,可在其上添加控件
  CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
  stateWindow = [[UIWindow alloc] initWithFrame:statusBarFrame];
  // 设置windowLevel为statusbar + 1 保证可以显示在statusbar上面
  stateWindow.windowLevel = UIWindowLevelStatusBar + 1;
  stateWindow.backgroundColor = [UIColor orangeColor];
  stateWindow.userInteractionEnabled = NO;
}

这样创建的与 statusbar 大小一样的UIWindow 已经好了,默认创建好 这个UIWindow 则已经添加上去了,只是默认不显示,可以使用下面来控制显示和隐藏。

window.hidden = YES; 
window.hidden = NO;

当然 UIwindow 还有个 makeKeyAndVisible 方法,这个方法会将新建的 UIWindow 设置为主窗口并显示,之后如果消失后,需要将原来的主窗口设置回来,不然会出现很多异常的问题,这里切记。

注意:控制新添加的 UIWindow 使用 hidden 来控制。尽量不要使用 makeKeyAndVisible

这里的 stateWindow 必须是私有变量或者全局变量,生命周期随所在控制器的生命周期。

添加Label

上面的 UIWindow 创建好了,那么要显示相关的提示文字,还需要添加 label,

label = [[UILabel alloc] initWithFrame:stateWindow.frame];
label.backgroundColor = [UIColor blackColor];
label.textColor = [UIColor whiteColor];
label.font=[UIFont systemFontOfSize:12];
label.textAlignment = NSTextAlignmentCenter;
[stateWindow addSubview:label];

之后设置 label的文字即可进行对其内容控制。

旋转问题处理

上面弄完基本上都完成,但是在旋转屏幕后,发现显示还是在原来的位置上,无法跟随系统的状态栏一起旋转。需要对 Window 设置空的UIViewController后才会跟着状态栏旋转。

// 需要设置一个空的ViewController 不然旋转屏幕后,不会跟着旋转坐标系
stateWindow.rootViewController = [UIViewController new];

旋转后,又发现了新的问题,在新建的 UIWindow 根据的是一开始时的状态长宽,但是旋转为横屏时,尺寸会发生变化,所以在每次显示 statusWindow 时重新设置下frame的大小,如下:

CGRect newFrame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, STATUSBAR_HEIGHT);
stateWindow.frame = newFrame;
label.frame = newFrame;

这里不直接取 statusbar 的frame,因为在statusbar 隐藏时获取的长宽为0,所以上面设置时取值为宽度和statusbar的高度,高度在一开始进行获取保存进常量中。

综上:对于显示覆盖 statusbar 的 UIWindow 已经完成啦,

其他细节

当我们显示了之后一般需要在延迟几秒后进行隐藏,在 Android 中一般实用Handler进行,或者实用timer进行执行操作。那么 ios 中怎么实用呢? 请看如下方法:

//延迟 3s 后执行 hideStateMsg 方法。
 [self performSelector:@selector(hideStateMsg) withObject:nil afterDelay:3.0];
 
 -(void)hideStateMsg {
  stateWindow.hidden = YES;
}

当然在执行之前可能还需要把之前的延时任务取消了,则有如下两种方法。

// 取消 self 对象中所有的延迟任务。
[NSObject cancelPreviousPerformRequestsWithTarget:self];

// 取消指定的函数的延迟执行操作。
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideStateMsg) object:nil];

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learn Python 3 the Hard Way

Learn Python 3 the Hard Way

Zed A. Shaw / Addison / 2017-7-7 / USD 30.74

You Will Learn Python 3! Zed Shaw has perfected the world’s best system for learning Python 3. Follow it and you will succeed—just like the millions of beginners Zed has taught to date! You bring t......一起来看看 《Learn Python 3 the Hard Way》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具