NavigationBar 是我们常用的,昨天想到了一个 手机 QQ 空间状态处对于 NavigationBar 处的处理,特此总结下这方面的。
在此,我们先了解下UINavigationController
的层次图,有助于我们更加的了解UINavigationBar
。
所以通俗地说就是,
UINavigationController
是个容器,里面可以装很多UIViewController
。装这么多UIViewController
让用户怎么控制它们呢,总得有个工具吧。这个工具就是UINavigationBar
。一个容器就这么一个bar,相当于控制台吧。但是,管理那么多UIViewController
,控制台上得按钮啊、标题啊,都千篇一律是不是看起来太无聊了。为了解决这个问题,UINavigationController
为每个UIViewController
生成一个UINavigationBarItem
,通过这个UINavigationBarItem
可以改变控制台“上面”得按钮和标题。
简单的说,UINavigationBar是UINavigationController的一个组成部分,就是上面的那个导航栏。UINavigationBar又有UINavigationItem组成。UINavigationItem则有title,按钮,提示文本等组成,就是我们看到的title文字,右上角的按钮。
- NavigationItem在NavigationBar代表一个ViewController,具体一点儿来说就是每一个加到NavigationController的viewController都会有一个对应的NavigationItem.
- 一个导航控制器控制多个视图,NavigationBar上的leftItem,rightItem,title是由当前的视图控制器控制的。
一、基本用法
self.title = @"TestTitle";// 与下面相同
//self.navigationItem.title = @"TestTitle";
// rightItem
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@"Done"
style:UIBarButtonItemStyleDone
target:self
action:@selector(doneTestAction)];
// leftItem
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@"Cancel"
style:UIBarButtonItemStylePlain
target:self
action:@selector(cancelTestAction)];
二、改变颜色
注意 title的颜色改变和 Item处的颜色方法是不同的
//改变颜色
self.navigationController.navigationBar.barTintColor = [UIColor blueColor];
//改变title颜色
self.navigationController.navigationBar.titleTextAttributes = @{
NSForegroundColorAttributeName : [UIColor redColor]
};
//改变 Item颜色
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
一般我们也常用下面这个方法改变,但是要注意我们一般只在AppDelegate中有效,或者是 UINavagaitonController中的 RootController 中设置有效,而且只有纯代码的时候才有效。storyboard 在根视图中设置也是没有效果的,以及其他的子视图单独设置都是没有效果的哦。
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
[UINavigationBar appearance].titleTextAttributes =@{
NSForegroundColorAttributeName : [UIColor whiteColor]
};
[[UINavigationBar appearance] setBarTintColor:[UIColor blueColor]];
当然也可一直用用图片改变的
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"nav"] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav"] forBarMetrics:UIBarMetricsDefault];
三、隐藏导航栏
self.navigationController.navigationBar.hidden = YES;
但是注意有时状态栏确是不会消失哦,解决这个问题则需要涉及到下面这个问题啦,提到edgesForExtendedLayout
self.edgesForExtendedLayout = UIRectEdgeNone;
edgesForExtendedLayout
是一个类型为UIExtendedEdge的属性,指定边缘要延伸的方向。 因为iOS7鼓励全屏布局,它的默认值很自然地是UIRectEdgeAll,四周边缘均延伸,就是说,如果即使视图中上有NavigationBar,下有tabBar,那么视图仍会延伸覆盖到四周的区域。
导航栏动态的消失
if (scrollView.contentOffset.y > 64) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
else
{
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
此处注意navigationBar.hidden与navigationBarHidden的区别:
两种方法都是可以隐藏导航栏的,隐藏之后依然可以使用push和pop方法。但是如果用navigationBar.hidden隐藏导航栏,我们可以继续使用navigationBarHidden提供的滑动pop效果,如果用navigationBarHidden,这个操作将无效;但前者navigationBar.hidden没有系统自动的动画效果。
ps 对状态栏处的处理:
此时注意 iOS 7 之后,我们改变状态栏的情况对plist info 的View controller-based status bar appearance
设置为YES,则状态栏会根据各个UIViewController的配置改变,UIViewController中如果需要改变状态栏则需要重载以下两个方法:
//状态栏是否隐藏
- (BOOL)prefersStatusBarHidden;
//状态栏样式
- (UIStatusBarStyle)preferredStatusBarStyle;
如果View controller-based status bar appearance为NO,则标示状态栏不受UIViewController的单独控制,那么这个时候状态栏的控制还和iOS7以前的方式一样,在需要修改的地方执行setStatusBarHidden。
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
这样状态栏就变成白色啦,但是 iOS 9之后 还是用前一种方法的,重写一下下面这个方法的。
- (UIStatusBarStyle)preferredStatusBarStyle;
四、屏幕原点的改变
此处不对比了 iOS 7之前的,ios6, 确实是从status bar下面开始布局 (0,20),iOS 7之后都是从status bar 左上角(0,0)开始布局的,但是有时,我们也会遇到在 NavigationController 中是以(0,64)布局的,此处又是什么情况呢?先来看一下下面三个属性:
- extendedLayoutIncludesOpaqueBars
默认值NO,这个属性指定了当Bar使用了不透明图片时,视图是否延伸至Bar所在区域;因此,如果我们自定义了nav bar背景图片,view会从导航栏下面开始布局。 - edgesForExtendedLayout
默认是UIRectEdgeAll,也就是全屏布局(iOS7中鼓励这样,这样可以透过半透明的bar看到一些模模糊糊的内容),如果设置为UIExtendedEdgeNone,view就不会延伸到bar的后面了 - automaticallyAdjustsScrollViewInsets
默认值是YES,如果视图里面存在唯一一个UIScrollView或其子类View,,那么它会自动设置相应的内边距(如果有navbar的时候,这个内边距是64,这样scrollview可以占满屏幕,内容在64像素以下,不会被遮到,滑动scrollview,可以透过半透明效果看到scrollview上面的内容)
所以说有时,我们发现原点位置变化了,就可以看看上述几个属性是否有设置改动的。经常我们用到 tableView 或 collectionView 的时候就需要设置 self.automaticallyAdjustsScrollViewInsets = NO, 不让其自动调整。
备注
http://blog.csdn.net/mad1989/article/details/41516743
http://www.cnblogs.com/ygm900/p/3659619.html