http://www.pchou.info/ios/2015/08/22/oc-statusbar.html

IOS的项目多数会遇到控制状态栏和导航栏的问题,比如隐藏状态栏、控制状态栏的文字颜色等,导航栏也有同样需求。本文总结一下操作方法。

首先一点,IOS的界面分为状态栏和导航栏,状态栏是指显示电池、时间的最顶部的一个窄条,高度为20个点;而导航栏是紧接着状态栏的44个点高度的横条,一般用于显示app标题,返回按钮等操作按钮。

在ios7之前,状态栏和导航栏是分开的,而从ios7开始状态栏和导航栏交织在一起了,状态栏变为透明,导航栏的高度变为44+20=64:

状态栏控制

对状态栏的控制分两种情况:全局设置和分页面设置。控制这两种模式的开关是info.plist文件的View controller-based status bar appearance配置项。

全局设置状态栏

info.plist文件的View controller-based status bar appearance设置为NO,即可开启全局设置,也就是说你在VC中对状态栏的控制都将无效,相比之下,是通过下面的代码来全局控制:

//设置状态栏的字体颜色模式
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
//设置状态栏是否隐藏
[[UIApplication sharedApplication] setStatusBarHidden:YES];

注意,我们并不能对状态栏的字体颜色做任意的控制,只有两种选择UIStatusBarStyleDefaultUIStatusBarStyleLightContent,前者是默认的黑色,而后者是白色。也就是说如果你的背景色是偏深色,那么设置状态栏的字体颜色为白色。另外,我们可以全局设置状态栏是否显示,但是一般而言app不会对所有界面都不显示状态栏,而是只在特定的页面需要隐藏状态栏,比如对于视频播放界面不希望显示状态栏。

对于状态栏的背景色设置,上面提到从ios7开始状态栏本身实际上是透明的,它的背景色其实取决于导航栏的背景色。下面会讲导航栏的设置。

分页面设置状态栏

info.plist文件的View controller-based status bar appearance设置为YES,即可开启由VC来控制状态栏的功能,在这种模式下,全局的设置将无效!!所以我们必须逐个页面对状态栏进行设置,否则状态栏将维持默认的黑色字体和默认为显示状态。

字体设置

对于设置状态栏字体颜色,分两种情况:VC是否属于UINavigationController中:

1) 当VC不在UINavigationController中时,在VC中添加一个方法

- (UIStatusBarStyle)preferredStatusBarStyle
{
//返回白色
return UIStatusBarStyleLightContent;
//返回黑色
//return UIStatusBarStyleDefault;
}

保险起见,在view的某个加载阶段比如viewWillAppear中,执行:

[self setNeedsStatusBarAppearanceUpdate];

2) 当VC在UINavigationController中时,VC并不能通过1)的方式控制状态栏的颜色,详见本文后面的参考资料,那么这个时候,有一个trick的方法可以在VC中间接的控制:

self.navigationController.navigationBar.barStyle = UIBarStyleBlack;

隐藏控制

对于控制状态栏的隐藏同样存在VC是否是根控制器的问题,也就说只有根控制器才能直接控制状态栏的显示与否。

1) 如果是VC本身就是根控制器,那么在VC中添加如下代码:

- (BOOL)prefersStatusBarHidden {
return YES;
}

当然,保险起见,在适当的时候调用

[self setNeedsStatusBarAppearanceUpdate];

2) 如果VC不是根控制器,那么不像控制字体颜色那样有trick,我们只能间接的通过在子VC中控制根VC,从而间接控制根控制器。那么这个方法就很多了,比如我的根VC是个tab的VC,首先现在tab的VC中,实现1):

@interface YYCTabBarController : RDVTabBarController

//定义一个变量来控制状态栏显示,子VC通过修改这个值来间接控制
@property (nonatomic,assign)BOOL statusBarHidden; @end @implementation YYCTabBarController - (BOOL)prefersStatusBarHidden {
return _statusBarHidden;
} @end

在子VC中:

- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated]; //rdv_tabBarController指向YYCTabBarController
if([self.rdv_tabBarController respondsToSelector:@selector(setStatusBarHidden:)]){
[self.rdv_tabBarController performSelector:@selector(setStatusBarHidden:) withObject:@(YES)];
[self setNeedsStatusBarAppearanceUpdate];
}
} - (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated]; if([self.rdv_tabBarController respondsToSelector:@selector(setStatusBarHidden:)]){
//注意对NO的情况,不能传@NO,只能传nil才能被当成NO
[self.rdv_tabBarController performSelector:@selector(setStatusBarHidden:) withObject:nil];
[self setNeedsStatusBarAppearanceUpdate];
}
}

可以看到在子VC中通过设置根VC的属性,并调用setNeedsStatusBarAppearanceUpdate后,根VC的prefersStatusBarHidden就会被调用,从而隐藏或显示状态栏。

导航栏控制

背景控制

在IOS7中使用barTintColor来控制导航栏的背景色:

[[UINavigationBar appearance] setBarTintColor:[UIColor yellowColor]];

这个设置方法可以在AppDelegate中设置,全局可以生效。

如果希望使用图片来作为导航的背景,那么需要注意的是ios7中图片的高度问题。上面提到过了,ios7导航栏的高度其实是算上状态栏的,即44+20=64个点的高度。可以通过setBackgroundImage来设置:

[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@ "nav_bg.png" ] forBarMetrics:UIBarMetricsDefault];

前景控制

前景控制分为标题控制和返回按钮(等系统按钮)的控制

标题需要通过setTitleTextAttributes来设置,相对比较复杂一些,例如:

NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
shadow.shadowOffset = CGSizeMake(0, 1);
[[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0], NSForegroundColorAttributeName,
shadow, NSShadowAttributeName,
[UIFont fontWithName:@ "HelveticaNeue-CondensedBlack" size:21.0], NSFontAttributeName, nil]];

设置返回按钮(等系统按钮)可以通过TintColor,直接来设置颜色

[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];

显示设置

有时我们希望导航栏不显示,而有时又希望显示,那么最好通过每个个体的VC来控制,如果某个VC需要与其他VC有所区别,那么最好是“负责到底”,即在进入VC时改变导航栏的显示状态,而退出时还原:

- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setHidden:YES];
[self.rdv_tabBarController setTabBarHidden:YES animated:NO];
} - (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setHidden:NO];
[self.rdv_tabBarController setTabBarHidden:NO animated:NO];
}

如何在有导航栏的情况下定位控件的Y

可能初学ios的同学(尤其是通过手写代码布局的同学)都会有这么个感受,为什么我的控件有的时候明明定位在VC上,但会被导航栏遮住,那么你可能会得出结论原点(0,0)是在屏幕的左上角被导航栏遮住的;而对于像UITableView这样的,设置了全屏铺满,怎么就没有被导航栏遮住呢?原点难道不在左上角?

笔者被这个问题困扰了很久,这里谈一下最近的一个理解。我们拿UITextView来看

当我们把一个UITextView放到一个没有导航的VC中时:

UITextView *textView = [[UITextView alloc] init];
textView.frame = CGRectMake(10, 200, 300, 120);
textView.backgroundColor = [UIColor redColor];
textView.text = @"游戏分两种,一种是在生活中玩的,另一种是生活在其中的。这两个世界相互矛盾,而两位约翰就分别属于这不同的世界。";
textView.font = [UIFont boldSystemFontOfSize:40];
textView.editable = NO;
[self.view addSubview:textView]

效果是这样的,看起来并没有什么问题

然而如果我们把这个VC放到一个导航控制器中,同样的代码却是这样结果

首先,看起来UITextView距离设备顶部的绝对距离似乎并没有变化,但是请注意UITextView的滚动条,滚动条竟然没有顶部对齐,而且文字也向下移位了,看起来空出一大块。仔细看空出的这段高度其实刚好是导航栏的高度64个点!!经过搜索,我发现只要设置如下代码即可恢复这种异常的状况:

self.automaticallyAdjustsScrollViewInsets = NO;

这下明白了,原来VC会对其内部的UIScrollView的内容部分进行一个Inset,这个Inset在上半部分刚好就对应导航栏的高度,而UIScrollView包括UITableViewUITextView等。到这里,似乎有些问题明朗了:

  1. VC中的view默认会对UIScrollView做一个适应导航栏的处理,由此推测,其实只要是VC中的控件,都是从设备左上角的(0,0)开始算的,只是对于UIScrollView,VC会自动调整一下内容的位置而已。
  2. 在有导航的情况下,可视范围的Y坐标就是从64开始的,除了UIScrollView的控件,定位的时候,都应当以(0,64)为原点;而UIScrollView如果是全屏的,那么无所谓,如果不是全屏的,请注意是否需要设置VC的automaticallyAdjustsScrollViewInsets

status 状态栏的更多相关文章

  1. status状态栏实现字符串走动

    <script type="text/javascript" language="javascript"> var i = 0; var str=& ...

  2. 2016/2/22 1、DOM的基本概念 2、Window对象操作 3、Windows.history对象 4、Window.location对象 5、Window.status对象

    1.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 2.Window对象操作 一.属性和方法: 属性(值或者子对象): op ...

  3. Doc

    一:window: 属性(值或者子对象):opener:打开当前窗口的源窗口,如果当前窗口是首次启动浏览器打开的,则opener是null,可以利用这个属性来关闭源窗口. 方法(函数):事件(事先设置 ...

  4. JS控制的事件

    鼠标点击弹出提示事件: <input type="button" value="鼠标点击弹出提示" onclick="DianJi()" ...

  5. JS操作页面

    DOM操作 1 windows对象操作 属性(值或者子对象): opener:打开当前窗口的源窗口,如果当前窗口是首次启动浏览器打开的,则opener是null.可以利用这属性来关闭源窗口 方法(函数 ...

  6. JavaScript(三)——DOM操作一

    一.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 二.Window对象操作 1.属性和方法: 属性(值或者子对象): op ...

  7. DOM、Window操作

    一.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 一.基本语法: 数据类型(字符串,小数,整数,布尔,时间) var, v ...

  8. JavaScript的DOM操作-非重点部分

    1.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档(HTML文档),对象是指文档中每个元素:模型是指抽象划的东西. 2.Windows对象操作 一.属性和方法 属性(值或者 ...

  9. 9.22 JS脚本语言DOM

    通用:onclick 鼠标单击ondblclick 鼠标双击onmouseover 鼠标放上onmouseout 鼠标离开onmousemove 鼠标移动 表单:onchang 表单的值改变onblu ...

随机推荐

  1. SVN配置管理(trunk、branches、tags)

    利用SVN的分支,合理地管理项目代码 由于SVN固有的特点,目录在SVN中并没有特别的意义,但是这三个目录却在大多数开源项目中存在,这是因为这三个目录反映了软件开发的通常模式. trunk是主分支,是 ...

  2. Javascript 笔记与总结(2-3)Javascript 运算符、控制结构与对象操作

    [连接运算符 + ] <script> console.log(1+2+'a'+3+4); </script> 输出: 3a34 [逻辑运算符]返回的是最早能判断表达式结果的那 ...

  3. Grand Theft Auto V (侠盗列车手5)图形研究

    原文地址:http://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study/   原文的简介: GTA(侠盗猎车)系列自从1997 ...

  4. 发现美的眼睛 Prepared SQL Statement

    DROP PROCEDURE IF EXISTS truncate_insert_sales_rank_toparow_month; DELIMITER /w/ CREATE PROCEDURE tr ...

  5. Capabilities and Limitations of Optimizing Compilers

    Computer Systems A Programmer's Perspective Second Edition #include <stdio.h> main(){ int wr; ...

  6. 微信内置浏览器UserAgent的判断

    需求分析 现在微信火了,很多线上的APP都希望通过分享的URL或直接的URL进行产品宣传(写这篇博文的时候,听说微信下个版本将要屏蔽微信中的URL链接),这些链接都将通过微信内置的浏览器打开.PM希望 ...

  7. phpcms list页实现分页

    {pc:content action="lists" catid="41" order="id ASC" num="1" ...

  8. Jquery小例子:全选按钮、加事件、挂事件;parent()语法;slideToggle()语法;animate()语法;元素的淡入淡出效果:fadeIn() 、fadeOut()、fadeToggle() 、fadeTo();function(e):e包括事件源和时间数据;append() 方法

    function(e): 事件包括事件源和事件数据,事件源是指是谁触发的这个事件,谁就是事件源(div,按钮,span都可以是事件源),时间数据是指比如点击鼠标的事件中,事件数据就是指点击鼠标的左建或 ...

  9. 初学MyBatis.net

    1.MyBatis.net介绍 MyBatis..net是一个简单,但是完整的ORM框架,它使你的实体对象与sql语句或者存储过程之间的映射变得很简单,并提供数据访问.包括两个主要框架 DataAcc ...

  10. FW:: ehcache memcache redis 三大缓存男高音

    最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特意归纳下各个缓存的优缺点,仅供参考!  Ehcache 在java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS ...