iOS 自定义导航栏笔记
一、UINavigationBar的结构
导航栏几乎是每个页面都会碰到的问题,一般两种处理方式:1.隐藏掉不显示 2.自定义
1. 添加导航栏
TestViewController * mainVC = [[TestViewController alloc] init];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:mainVC];
self.window.rootViewController = nav;
2. 隐藏导航栏
在的TestViewController.m文件中,使用以下代码:
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
//self.navigationController.navigationBar.hidden = YES;
}
说明:通过属性直接设置之所以能成功,是因为虽然navigationBar是readonly,但是hidden是默认的(readwrite)。建议使用第一个,通过发送消息来设置。
3. 修改导航栏背景色
由于系统自带的导航栏已经不能满足用户的审美需求,因此开发中导航栏或多或少都被自定义了;即便只是修改了背景色或是字体颜色。
- 方式一:通过代理来设置
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];效果图
说明:为什么能修改所有导航栏的背景色?
- 查看UINavigationBar发送的消息appearance,是一个名为UIAppearance协议。根据官网解释:UIAppearance是一个外观协议(装饰模式)。要想改变外观需要实现此协议,因此UINavigationBar内部肯定实现了此协议。
- 查看头文件UIAppearance协议里面有4个方法,但是根据官网文档,iOS9以后有两个方法被废弃。因此只有下面两个可用,都返回的是类的对象,因此可以给此类发送修改外观的消息.比如:setBarTintColor。其实这里拿到对象后可以任意修改。
+ (instancetype)appearance;
+ (instancetype)appearanceForTraitCollection:(UITraitCollection *)trait
- 方式二、直接通过属性设置,或发送消息来设置
在的TestViewController.m文件中,使用以下代码:
- (void)viewDidLoad {
[super viewDidLoad];
// 无效果
self.navigationController.navigationBar.backgroundColor = [UIColor redColor];
// 可行
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav.png"] forBarMetrics:UIBarMetricsDefault];
}
说明:
- 下面代码为什么无效果,其实看一下结构图就明白了。
self.navigationController.navigationBar.backgroundColor = [UIColor redColor];
没错:这样修改的是navigationBar的背景色,而navigationBar里面添加了UIView和UIImageView,UILabel等控件,覆盖了navigationBar。
- 那么如何来修改?
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"yao_1"] forBarMetrics:UIBarMetricsDefault];
通过添加背景图,使用默认的模式。
注意:这里会出现状态栏背景色也变化的问题,其实这是由于在navigationBar添加的控件自动延伸到边界造成的。如果只是修改导航栏的背景色,完全没必要再给navigationBar添加控件了,给navigationBar堆太多的无用控件,不能忍。
// 设置透明
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"yao_1"] forBarMetrics:UIBarMetricsCompact];
// 修改navigationBar的背景色
self.navigationController.navigationBar.backgroundColor = [UIColor redColor];
这样修改navigationBar背景色,才有种很舒畅的感觉,有木有。因为我就只是要修改navigationBar的背景色而已么。效果图:
为什么要这样
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
或者为什么要这样
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"yao_1"] forBarMetrics:UIBarMetricsDefault];
UINavigationBar和UINavigationController、UIViewController关系
1.导航栏类名:UINavigationBar,是导航控制器(UINavgationController)下得一个属性,一般给一个视图控制器(TestViewController)添加导航栏,也就是把它添加为导航控制器(UINavgationController)的根视图控制器。
2.在此视图控制器中为什么可以直接操作导航控制器,因为TestViewController类是自定义的继承自UIViewController类的。而UIViewController类中有一个类别,声明了UINavgationController类的一个属性。在第一步的时候,把这个属性设置为上面导航控制器的对象。
3.UINavigationBar对照图如下:
UINavgationBar结构图说明:
- 从图中的对照关系可以看到,UINavigationBar包含一个:UINavigationBarBackground控件(已经延伸到边界,覆盖掉了导航栏),另一个UINavigationBarBackIndicatorView(其实就是那个蓝色的返回按钮,当push进来一个ViewController才会显示)
- UINavigationBarBackground控件里面包含:UIBackdropView(UIBackdropEffectView标识阴影视图),UIImageView
总结:
可以看到,UINavigationBarBackIndicatorView(返回按钮只占了左边一部分区域,并且在push新的视图控制器时才显示。因此,显示在最上面的是UIImageView)。所以,这才是通过代码
self.navigationController.navigationBar.backgroundColor = [UIColor redColor];
*修改背景色,老是被遮住的根本原因。解决方法,因此掉UIImageView控件,或者干脆给UIImageView设置一张你想要的背景色的图片。*
二、UINavigationBar的自定义
1. 自定义
一般自定义分三种情况:左侧、右侧和中间视图
- 自定义左侧按钮
- (void)viewDidLoad {
[super viewDidLoad];
// 自定义导航栏左侧按钮
UIButton * leftBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
leftBtn.frame = CGRectMake(0, 7, 83, 30);
leftBtn.backgroundColor = [UIColor orangeColor];
[leftBtn addTarget:self action:@selector(onTap) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
self.navigationItem.leftBarButtonItem = leftItem;
}
// 点击事件处理
- (void)onTap {
NSLog(@"点击了导航栏左侧按钮");
}
自定义右侧按钮
和自定义左侧按钮方法类似,差别如下:
self.navigationItem.rightBarButtonItem = rightItem;自定义中间视图
UIView * centerView = [[UIView alloc] initWithFrame:CGRectMake(0, 7, 110, 30)];
centerView.backgroundColor = [UIColor greenColor];
self.navigationItem.titleView = centerView;2. 结构分析
从自定义的代码看到,自定义都是在修改navigationItem里面的东西。查看头文件可知,TestViewController之所以可以操作navigationItem,和上面UINavigationController实现方式一样。
UINavigationBar类中有一个items集合,存储navigationItem和其他相关内容。UINavigationItem类里面存储leftBarButtonItems、rightBarButtonItems等集合。同时也会有leftBarButtonItem、rightBarButtonItem控件,根据集合是否为空来决定是否创建和显示这些控件。
因此,当不设置内容时,默认集合为空,所有控件也就不显示。
3. 手写代码技巧
对于导航栏的自定义,大部分app都是左侧为"返回",右侧为"地图",“扫码”等按钮,中间除显示标题外,可能会自定义个分段按钮,选择菜单等。而对于这些自定义的按钮和视图,尺寸都是根据图片尺寸和导航栏的宽高凭感觉设置的(总之,我以前是这样>.<)。
今天在测试iOS7的布局使用了SB,发现控件拖上去它会自适应系统给定的尺寸。然后我绑定控件获取了这些控件的尺寸。测试了iPhone4s和iPhone6,获取到的左侧和右侧按钮尺寸:frame = {0,7,83,30},中间的视图尺寸:frame = {0,7,110,30}。
这样,以后导航栏按钮没有什么特殊要求,就可以都按这个尺寸设置了。
iOS 自定义导航栏笔记的更多相关文章
- iOS 自定义导航栏 和状态栏
一.更改状态栏颜色 (StatusBar) 就是比如导航栏是红色的状态栏是绿色的. 要实现这样的效果其实很简单,就是添加一个背景view. 简单的实现过程如下: 1 // 设置导航颜色 可用 2 [s ...
- ios 自定义导航栏,开启侧滑返回手势
自定义一个常用ListViewController .h文件 #import <UIKit/UIKit.h> @interface ListViewController : UIViewC ...
- IOS 自定义导航栏背景
//- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics NS_AV ...
- iOS 自定义导航栏
参考链接:https://blog.csdn.net/huanglinxiao/article/details/100537988 demo下载地址:https://github.com/huangx ...
- iOS个人中心渐变动画、微信对话框、标签选择器、自定义导航栏、短信验证输入框等源码
iOS精选源码 简单的个人中心页面-自定义导航栏并予以渐变动画 程序员取悦女票的正确姿势---Tip1(iOS美容篇) iOS 前台重启应用和清除角标的问题 微信原生提醒对话框3.0 JHLikeBu ...
- iOS:自定义导航栏,随着tableView滚动显示和隐藏
自定义导航栏,随着tableView滚动显示和隐藏 一.介绍 自定义导航栏是APP中很常用的一个功能,通过自定义可以灵活的实现动画隐藏和显示效果.虽然处理系统的导航栏也可以实现,但是这个是有弊端的,因 ...
- ios7以上自定义导航栏标题的字体大小及颜色的方法
自定义导航栏的字体和颜色,只需要自定义一个lable,然后将lable添加到导航栏的titleview中就可以了 代码如下 UILabel *label = [[UILabel alloc] init ...
- iOS 11 导航栏 item 偏移问题 和 Swift 下 UIButton 设置 title、image 显示问题
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- 解决 ios7.0 以后自定义导航栏左边按钮靠右的问题
解决 ios7.0 以后自定义导航栏左边按钮靠右的问题 www.111cn.net 编辑:edit02_lz 来源:转载 最近开发了一个ios的app,在ios7.0+出现自定义导航栏左边按钮出现靠右 ...
随机推荐
- 在GNU/Linux下设置与定时更换桌面壁纸
1 简介 在电脑桌面设置一组可以定时更换的壁纸已经不是什么新奇的功能了.比如,Windows 7.KDE桌面环境都可以实现这样的效果.可是,自己目前使用的Debian系统并未安装KDE.GNOME这样 ...
- ASP.NET使用ImageMap控件
文章来自:http://www.baike369.com/content/?id=5773
- Openjudge-NOI题库-Pell数列
题目描述 Description Pell数列a1, a2, a3, ...的定义是这样的,a1 = 1, a2 = 2, ... , an = 2 * an − 1 + an - 2 (n > ...
- [Linux]当一个棘手问题需要即可定位,如何协助开发,缩小定位范围
写在前面:前段时间,朋友给我说了一个她亲身经历的某知名企业面试故事,面试结束感觉自己已脱了一层皮...面试官的问题并不刁钻,但是却是步步紧逼,而且有点类似拜占庭将军问题,只是拜占庭将军问题是所有的假设 ...
- asp.net MVC Session锁的问题
一直在用Session,对Session锁并没有太多的关注,可能是平时没有注意.前段时间突然发现,一个Ajax Get请求,直接访问地址,只需要几十ms,但是在页面中加载,却需要2s.最后定位到Ses ...
- 小白学C++的小问题
昨天开始学习C++,使用的visual studio 2012. 1命名要有意义,避免用a,b,c,尽量使用num,result等让人看见就能明白相关含义的名字 2要有一定的注释,注释和有意义的命名可 ...
- JavaScript 属性类型(数据属性 访问器属性)
ECMA-2把对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.” 严格来说,这就相当于说对象是一组没有特定顺序的值.对象的属性或方法都有一个名字,而每个名字映射到一个值.我们可以把E ...
- php 微信 统一下单 接口实例
<?phpclass wechatAppPay { //接口API URL前缀 const API_URL_PREFIX = 'https://api.mch.weixin.qq.com'; / ...
- kafka_2.11-0.10.0.0安装步骤
Kafka安装配置 我们使用5台机器搭建Kafka集群: 1. cluster-1-namenode-1-001 172.16.0.147 2. cluster-1-datanode-1- ...
- 1.部分(苹果)移动端的cookie不支持中文字符,2.从json字符串变为json对象时,只支持对象数组
1.移动端的cookie不支持中文字符.可以用编码,解码的方式解决. 2.json字符串变成相应 的,json对象数组字符串.就这样 3.不同客户端(移动端.电脑)的请求,在C#服务端的取时间的格式竟 ...