摘要:原文状态栏和导航栏的控制问题的项目多数会遇到控制状态栏和导航栏的问题,比如隐藏状态栏控制状态栏的文字颜色等,导航栏也有同样需求。
原文:IOS状态栏和导航栏的控制问题
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];
注意,我们并不能对状态栏的字体颜色做任意的控制,只有两种选择UIStatusBarStyleDefault和UIStatusBarStyleLightContent,前者是默认的黑色,而后者是白色。也就是说如果你的背景色是偏深色,那么设置状态栏的字体颜色为白色。另外,我们可以全局设置状态栏是否显示,但是一般而言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包括UITableView和UITextView等。到这里,似乎有些问题明朗了:
VC中的view默认会对UIScrollView做一个适应导航栏的处理,由此推测,其实只要是VC中的控件,都是从设备左上角的(0,0)开始算的,只是对于UIScrollView,VC会自动调整一下内容的位置而已。
在有导航的情况下,可视范围的Y坐标就是从64开始的,除了UIScrollView的控件,定位的时候,都应当以(0,64)为原点;而UIScrollView如果是全屏的,那么无所谓,如果不是全屏的,请注意是否需要设置VC的automaticallyAdjustsScrollViewInsets。
参考资料
定制iOS 7中的导航栏和状态栏
iOS Programming 101: How to Customize Navigation Bar and Back Button
How to change Status Bar text color in iOS 7
preferredStatusBarStyle isn"t called
Blank space at top of UITextView in iOS 7
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/15835.html
摘要:前言我们先一起来回顾一下实现沉浸式状态栏的一般套路。从以上版本才是真正的可以设置沉浸式体验,但也仅仅是操作状态栏和导航栏的显示与隐藏。属性解释设置了表明会负责系统的绘制,绘制透明背景的系统状态栏和导航栏,然后用和的颜色填充相应的区域。 前言 我们先一起来回顾一下实现沉浸式状态栏的一般套路。在Android上,关于对StatusBar(状态栏)的操作,一直都在不断改善,并且表现越来越好,...
摘要:背景在做小程序时,关于默认导航栏,我们遇到了以下的问题手机对于页面的展示不一致,安卓的显示不居中页面的只支持纯文本级别的样式控制,不能够做更丰富的效果左上角的事件无法监听定制路由导航单一,只能够返回上一页,深层级页面的返回不够友好探索小程序 背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android、IOS手机对于页面title的展示不一致,安卓title的显示不居中...
摘要:背景在做小程序时,关于默认导航栏,我们遇到了以下的问题手机对于页面的展示不一致,安卓的显示不居中页面的只支持纯文本级别的样式控制,不能够做更丰富的效果左上角的事件无法监听定制路由导航单一,只能够返回上一页,深层级页面的返回不够友好探索小程序 背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android、IOS手机对于页面title的展示不一致,安卓title的显示不居中...
摘要:使用该标志位时,也需要在中声明,即新的名称,否则锁屏实质上还是在建立在原来的栈中。设置锁屏的内部也要做相应的配置,让在锁屏时也能够显示,同时去掉系统锁屏。 本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一、为什么需要自定义锁屏页 锁屏作为一种黑白屏时代就存在的手机功...
摘要:在当前最新版本中将删除。推荐设置的位置,默认在底部,安卓默认在顶部。五完整代码这里有个用实现网易新闻客户端的项目,里面除了使用了外,还包括其他一些常用库的使用,需要的可以点击传送门 Fb在React Native当前最新版本0.44中将Navigator删除。推荐使用react-navigation,据称此库有原生般的性能体验效果。可能会成为未来React Native导航组件的主流军...
阅读 2612·2021-11-18 10:02
阅读 2274·2021-10-12 10:11
阅读 1019·2021-10-11 10:58
阅读 3052·2019-08-30 15:54
阅读 502·2019-08-30 13:59
阅读 505·2019-08-29 13:07
阅读 1290·2019-08-26 11:55
阅读 2018·2019-08-26 10:44