博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ios 自定义状态栏
阅读量:7094 次
发布时间:2019-06-28

本文共 6188 字,大约阅读时间需要 20 分钟。

  hot3.png

公司的开发的项目要求在状态栏上边加入程序下载的进度条,之前写的程序,由于是根据ipad的朝向来设置自定义的状态栏的frame,以及子视图的frame和transform,出现一些不太容易解决的bug。这两天正好项目不太紧,就好好学习一下这方面的知识,以下是我所总结的一点经验:

这里说明一下,Apple没有开放的状态栏的API,在ios 的官方文档没有提到修改Window Level的方式;

先看一下Window Level的可用的值包括:

1: typedef CGFloat UIWindowLevel;
2: const UIWindowLevel UIWindowLevelNormal; // 0.0
3: const UIWindowLevel UIWindowLevelAlert; // 2000.0
4: const UIWindowLevel UIWindowLevelStatusBar; // 1000.0

默认我们的UIView layer都是在UIWindowLevelNormal上,这也就是为什么系统弹出来的对话框在我们的视图之上,因为它的Window Level级别更高。

根据WindowLevel的原理我们也就知道,如果想在系统的状态栏上,添加自定义的状态栏,就需要比UIWindowLevelStatusBar的级别更高,接下来,用代码说明一下:

首先,先建一个Single View Application,名字自定义就可以了,

然后,新建一个类命名为: StatusBarOverlay 继承自UIWindow类,代码:

StatusBarOverlay.h文件

1: #import 
2:  
3: @interface StatusBarOverlay : UIWindow{
4:  UIView *contentView;
5:  UILabel *textLabel;
6: }
7:  
8: @property (nonatomic, retain) UIView *contentView;
9:  
10: @property (nonatomic, retain) UILabel *textLabel;
11:  
12: @end

StatusBarOverlay.m文件

1: //
2: //  StatusBarOverlay.m
3: //  StatusBarDemo
4: //
5: //  Created by jordy wang on 12-8-7.
6: //  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7: //
8:  
9: #import "StatusBarOverlay.h"
10:  
11: #define STATUS_BAR_ORIENTATION [UIApplication sharedApplication].statusBarOrientation
12: #define ROTATION_ANIMATION_DURATION [UIApplication sharedApplication].statusBarOrientationAnimationDuration
13:  
14:  
15: @interface StatusBarOverlay()
16:  
17: - (void)initializeToDefaultState;
18: - (void)rotateStatusBarWithFrame:(NSValue *)frameValue;
19: - (void)setSubViewHFrame;
20: - (void)setSubViewVFrame;
21: @end
22:  
23:  
24: @implementation StatusBarOverlay
25: @synthesize contentView;
26: @synthesize textLabel;
27:  
28: //重写init方法
29: - (id)init
30: {
31:  self = [super initWithFrame:CGRectZero];
32:  if (self) {
33:  self.windowLevel = UIWindowLevelStatusBar + 1;
34:  self.frame = [UIApplication sharedApplication].statusBarFrame;
35:  [self setBackgroundColor:[UIColor orangeColor]];
36:  [self setHidden:NO];
37:
38:  //内容视图
39:  UIView *_contentView = [[UIView alloc] initWithFrame:self.bounds];
40:  self.contentView = _contentView;
41:  [self.contentView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
42:  [self.contentView setBackgroundColor:[UIColor cyanColor]];
43:  [self addSubview:self.contentView];
44:  [_contentView release];
45:
46:
47:  //添加textLabel
48:  UILabel *_textLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, 0, CGRectGetWidth(self.frame)-60, CGRectGetHeight(self.frame))];
49:  self.textLabel = _textLabel;
50:  [self.textLabel setBackgroundColor:[UIColor blueColor]];
51:  [self.textLabel setFont:[UIFont systemFontOfSize:12]];
52:  [self.textLabel setTextAlignment:UITextAlignmentCenter];
53:  [self.textLabel setTextColor:[UIColor blackColor]];
54:  [self.textLabel setText:@"自定义的状态栏 author by jordy"];
55:  [self.contentView addSubview:self.textLabel];
56:  [_textLabel release];
57:
58:  //注册监听---当屏幕将要转动时,所出发的事件(用于操作本视图改变其frame)
59:  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willRotateScreenEvent:) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
60:  //初始化
61:  [self initializeToDefaultState];
62:  }
63:
64:  return self;
65: }
66:  
67:  
68:  
69:  
70: //初始化为默认状态
71: - (void)initializeToDefaultState
72: {
73:  //获取当前的状态栏位置
74:  CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
75:  //设置当前视图的旋转, 根据当前设备的朝向
76:  [self rotateStatusBarWithFrame:[NSValue valueWithCGRect:statusBarFrame]];
77:
78:
79:
80: }
81:  
82:  
83: //旋转屏幕
84: - (void)rotateStatusBarWithFrame:(NSValue *)frameValue
85: {
86:  CGRect frame = [frameValue CGRectValue];
87:  UIInterfaceOrientation orientation = STATUS_BAR_ORIENTATION;
88:
89:  if (orientation == UIDeviceOrientationPortrait) {
90:  self.transform = CGAffineTransformIdentity; //屏幕不旋转
91:  [self setSubViewVFrame];
92:  }else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
93:  self.transform = CGAffineTransformMakeRotation(M_PI); //屏幕旋转180度
94:  [self setSubViewVFrame];
95:  }else if (orientation == UIDeviceOrientationLandscapeRight) {
96:  self.transform = CGAffineTransformMakeRotation((M_PI * (-90.0f) / 180.0f)); //屏幕旋转-90度
97:  [self setSubViewHFrame];
98:  }else if (orientation == UIDeviceOrientationLandscapeLeft){
99:  self.transform = CGAffineTransformMakeRotation(M_PI * 90.0f / 180.0f); //屏幕旋转90度
100:  [self setSubViewHFrame];
101:  }
102:
103:  self.frame = frame;
104:  [self.contentView setFrame:self.bounds];
105: }
106:  
107: //设置横屏的子视图的frame
108: - (void)setSubViewHFrame
109: {
110:  self.textLabel.frame = CGRectMake(30, 0, 1024-60, 20);
111: }
112: //设置竖屏的子视图的frame
113: - (void)setSubViewVFrame
114: {
115:  self.textLabel.frame = CGRectMake(30, 0, 748-60, 20);
116: }
117:  
118: #pragma mark -
119: #pragma mark 响应屏幕即将旋转时的事件响应
120: - (void)willRotateScreenEvent:(NSNotification *)notification
121: {
122:  NSValue *frameValue = [notification.userInfo valueForKey:UIApplicationStatusBarFrameUserInfoKey];
123:  [self rotateStatusBarAnimatedWithFrame:frameValue];
124: }
125:  
126: - (void)rotateStatusBarAnimatedWithFrame:(NSValue *)frameValue {
127:  [UIView animateWithDuration:ROTATION_ANIMATION_DURATION animations:^{
128:  self.alpha = 0;
129:  } completion:^(BOOL finished) {
130:  [self rotateStatusBarWithFrame:frameValue];
131:  [UIView animateWithDuration:ROTATION_ANIMATION_DURATION animations:^{
132:  self.alpha = 1;
133:  }];
134:  }];
135: }
136:  
137: - (void)dealloc
138: {
139:  [[NSNotificationCenter defaultCenter] removeObserver:self];
140:  [textLabel release];
141:  textLabel = nil;
142:
143:  [contentView release];
144:  contentView = nil;
145:
146:  [super dealloc];
147: }
148:  
149: @end

由于代码比较简单,并且我在上述代码里有相应的注释,这里需要说明一点的是,默认我们继承自UIWindow的StatusBarOverlay类是hidden状态,需要在初始化的时候设置它的hidden属性为NO,

在屏幕旋转过程中,自定义的状态栏与UIViewController之间的旋转是分离的,所以我们需要做一个隐藏的动画,在旋转过程前先隐藏自定义的状态栏,旋转结果后设置显示状态。

如果需要做一种动画,比方从底部下移显示一条信息,隔N秒后又自动收回的动画,直接设置自定义的视图的y坐标就可以了,默认y坐标设置是0。

最后, 使用它的方式也比较简单,只需要初始化,代码:

StatusBarOverlay *statusBarOverlay = [[StatusBarOverlay alloc] init];

由于我公司的需求是开机自动下载的功能,所以我在初始化的时候,是放在了AppDelegate中。

转载于:https://my.oschina.net/amoyai/blog/97263

你可能感兴趣的文章
UVA1479 Graph and Queries
查看>>
Mini program
查看>>
nvl函数和decode
查看>>
Windows 网卡超过序列
查看>>
shiro-简介
查看>>
nndl_读数笔记
查看>>
优化网站设计系列文章总结和导读
查看>>
ORACLE SET命令
查看>>
【Python3爬虫】第一个Scrapy项目
查看>>
数据结构之最短路径(1) [迪杰斯特拉算法]
查看>>
static变量
查看>>
dubbo之结果缓存
查看>>
java.lang的接口
查看>>
HDU 3001 Travelling 【状态压缩DP】
查看>>
HDU 1116 Play on Words【欧拉通路or回路】
查看>>
php or java?choose。
查看>>
C++静态库与动态库
查看>>
javascript数据结构与算法--基本排序算法(冒泡、选择、排序)及效率比较
查看>>
first day~
查看>>
字符串的替换问题
查看>>