UINavigationBar的高度在苹果官方的SDK中是固定的44个点,但是实际项目中我们却有可能遇到这样的情况,如下图:

这样的一个UINavigationBar的高度达到了84个点,这就需要我们自定义系统自带的UINavigationBar的高度,但是系统并没有直截了当的方法来调整这个NavigationBar的Height,于是我进行了以下的尝试。

在需要进行调整的那个ViewController类的ViewWillApplear这个方法对 self.navigationController.navigationBar的frame进行赋值,其中frame.size.height变为我 们需要的新高度(本例中为84),然后在ViewWillDisappear这个方法中将frame再改回去就可以了。

注:这里将代码写在ViewWillAppear/DisAppear里面的原因是根据这个自定义高度UINavigationBar只在某一 个界面出现,如果你所有的UINavigationBar的高度是统一的,那么就没必要这么写,只需要写在第一次出现的ViewController的 ViewDidLoad消息里面就可以了。

代码如下:

-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
CGRect rect = self.navigationController.navigationBar.frame;
self.navigationController.navigationBar.frame = CGRectMake(rect.origin.x,rect.origin.y,rect.size.width,84);
}

-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
CGRect rect = self.navigationController.navigationBar.frame;
self.navigationController.navigationBar.frame = CGRectMake(rect.origin.x,rect.origin.y,rect.size.width,44);
}

1
2
3
4
5
6
7
8
9
10
11

- ( void ) viewWillAppear : ( BOOL ) animated {

[ super viewWillAppear :animated ] ;

CGRect rect = self . navigationController . navigationBar . frame ;

self . navigationController . navigationBar . frame = CGRectMake ( rect . origin . x , rect . origin . y , rect . size . width , 84 ) ;

}

- ( void ) viewWillDisappear : ( BOOL ) animated {

[ super viewWillDisappear :animated ] ;

CGRect rect = self . navigationController . navigationBar . frame ;

self . navigationController . navigationBar . frame = CGRectMake ( rect . origin . x , rect . origin . y , rect . size . width , 44 ) ;

}

OK,运行!UINavigationBar的高度正确地发生变化,事情就这么愉快地解决了!等等,导航栏上的标题和返回按钮的位置却都贴到最下面了,如下图:

为什么会是这样?发生了什么?我也不知道!但是现在很明显就是需要我们去调整这两个“UIView”的frame,把他们向上移动40个点,为之后要添加的其他控件留出空间。很简单,对吧?

然后,数个小时过去后……

我靠,这些货特么根本不是UIView嘛!

返回按钮是UIBarButtonItem,继承自UIBarItem,UIBarItem继承自NSObject,标题这个就更悲剧了,如果 你默认使用ViewController的title属性做为标题(本例就是),那么self.navigationItem.titleView这个值 为nil,更改nil的frame什么事情也不会发生。

这期间我试过各种非正常手段去找到他们,包括遍历UINavigationBar的view hierarchy(视图层级),试图使用UIBarButtonItem的私有变量,尝试修改UIBarButtonItem的 CustomView.frame等……都无功而返。

然后开始上Google搜索,StackOverflow一片找,SO上果然大神云集,问题的解答也相当高大上。

答案基本上有2种:
1、不用系统的NavigationBar啦,咱们自定义一个就好啦,然后重载layoutSubView里面的怎样怎样云云。
2、这个简单,我写了个NavigationBar的分类(Category),里面加个什么消息xxx。

小菜我一看到自定义控件神马的立即就給外国大爷们跪了,Category什么的更是从来没用过……其实我只需要更改一下这两个控件的高度而已,用不用这么暴力?

于是我开始查文档,终于被我找到下面这两个消息:

UINavigationBar下:

- (void)setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics

官方描述:
Sets the title’s vertical position adjustment for given bar metrics.
调整某个BarMetrics(这个不知道怎么翻译)下标题的垂直位置。

UIBarButtonItem下:

- (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics

官方描述: Sets the background vertical position offset for
given bar metrics.This offset is used to adjust the vertical centering
of bordered bar buttons within the bar.
调整某个BarMetrics(这个不知道怎么翻译)下背景的垂直位置的偏差值,这个偏差值用来调整该圆角按钮的垂直中心在Bar内的位置。

OhMyGod,终于找到组织了!赶紧试一下,还是刚才的ViewController,在ViewWillAppear这个消息中再加上这么两句:

[self.navigationController.navigationBar setTitleVerticalPositionAdjustment:-40.0 forBarMetrics:UIBarMetricsDefault];
[self.navigationItem.leftBarButtonItem setBackgroundVerticalPositionAdjustment:-40.0 forBarMetrics:UIBarMetricsDefault];
1
2

[ self . navigationController . navigationBar setTitleVerticalPositionAdjustment : - 40.0 forBarMetrics : UIBarMetricsDefault ] ;

[ self . navigationItem . leftBarButtonItem setBackgroundVerticalPositionAdjustment : - 40.0 forBarMetrics : UIBarMetricsDefault ] ;

注:这里使用leftBarButtonItem是因为我使用了自定义图片的返回按钮,这时leftBarButton就替代了backBarButton。

不要忘了在ViewWillDisappear的时候再把标题的位置调整回来,不然当标题就会跳到屏幕的最上方了;另一方面,返回按钮却不用设置了,这两行代码的作用机制不一样,返回按钮只和当前的ViewController有关:

[self.navigationController.navigationBar setTitleVerticalPositionAdjustment:0.0 forBarMetrics:UIBarMetricsDefault];
1

[ self . navigationController . navigationBar setTitleVerticalPositionAdjustment : 0.0 forBarMetrics : UIBarMetricsDefault ] ;

运行结果:

太棒啦!终于成功了!标题和返回按钮的垂直位置按照我们设置的向上移动了40个点!

后面的事情就简单了,按照设计湿GG或者设计师MM的要求把相应的UI控件加到self.navigationController.navigationBar中,收工!

注:上述运行结果的前提是使用自定义图片的leftBarButtonItem作为返回按钮替代系统默认的 backBarButtonItem,并且你的leftBarButtonItem是使用 initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action这个方法创建的(原因我后面会讲)。换句话说,在你的ViewController或者它的父类的 ViewDidLoad方法里,应该有类似下面的两行代码:

UIBarButtonItem * item =[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@“这里是你的某个图片名"] style:UIBarButtonItemStyleBordered target:self action:@selector(你的某个方法名)];
self.navigationItem.leftBarButtonItem = item;
1
2

UIBarButtonItem * item = [ [ UIBarButtonItem alloc ] initWithImage : [ UIImage imageNamed : @ “这里是你的某个图片名" ] style : UIBarButtonItemStyleBordered target : self   action : @ selector ( 你的某个方法名 ) ] ;

self . navigationItem . leftBarButtonItem = item ;

如果你的需求刚好能用这个方法解决,那么恭喜你,因为小菜能拿出的干货就只有这么多了,后面的就全是困惑了……orz

做为一个iOS Level1的菜鸟,在费了好大的劲终于找到问题的解决方法之后,欣喜是肯定的,想得瑟一下是必然的,于是飘飘乎就想把相关的方法研究研究,搞个通用的解决方案出来。于是,噩梦开始了……

N多个小时过去了,毛个解决方案没搞出来,却搞出来了很多个问题……

问题1:系统默认的导航栏返回按钮垂直位置无法调节。

当返回按钮使用系统默认的backBarButtonItem的时候,使用UIBarButtonItem的- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics来调整它的垂直位置,不起作用。

我进行了各种尝试,但是backBarButtonItem一直是nil,文档上说它会根据上一个ViewController的title属 性来创建这个按钮,但是我找不到这个时机来调整执行上面这个消息。更准确的问题可能是,下图中的这个消息到底应该怎么用才能看到效果呢?

问题2:自定义的返回按钮在导航栏中的垂直位置仅在某一种情况下可以调节。

后来我又发现,即使不用系统默认地返回按钮,使用自定义的leftBarButtonItem,也只在使用 initWithImage:style target:action:这个方法创建的UIBarButtonItem时生效,使用其他init方法情况一律无效。至于什么原因不明觉厉。

这两个问题我百撕不得姐,求大家指教,提前说声谢谢!

copy from http://iosinit.com/?p=757

iOS 如何自定义NavigationBar的高度的更多相关文章

  1. 自定义navigationBar的高度

    原来看过一些解决办法,都不太好,最近解决自定义 tab bar的高度的问题,从中受到启发,找到下面的解决办法. 个人觉得和网上找到的其它方法比还是很简洁的. 关键是要调整navBarTransitio ...

  2. iOS 如何自定义UISearchBar 中textField的高度

    iOS 如何自定义UISearchBar 中textField的高度 只需设置下边的方法就可以 [_searchBar setSearchFieldBackgroundImage:[UIImage i ...

  3. ios 实现自定义状态栏StatusBar 和 导航栏navigationBar 的状态和颜色

    很多app中可以看到不同与导航栏的状态栏的颜色,他妈的真绕嘴. 一.更改状态栏颜色 (StatusBar) 就是比如导航栏是红色的状态栏是绿色的. 要实现这样的效果其实很简单,就是添加一个背景view ...

  4. 【swift,oc】ios开发中巧用自动布局设置自定义cell的高度

    ios开发中,遇到自定义高度不定的cell的时候,我们通常的做法是抽取一个frame类,在frame类中预算好高度,再返回. 但是苹果出来自动布局之后...春天来了!!来看看怎么巧用自动布局设置自定义 ...

  5. iOS自定义NavigationBar

    日常开发中少不了用到UINavigationController,但是很多情况都要自定义NavigationBar.依稀记得自己刚开始也踩了好多坑,凑今天有空,就把想到的写下来.有时间了,考虑再把自定 ...

  6. 79.iOS 设备的UI规范和iOS各控件默认高度

    iOS设备的UI 规范 iPhone界面尺寸 iPhone图标尺寸 iPad的设计尺寸 iPad图标尺寸 iPhone设备尺寸分辨率比例 iPhone各设备 launch image iOS 各种控件 ...

  7. iOS 隐藏自定义tabbar

    iOS  隐藏自定义tabbar -(void)viewWillAppear:(BOOL)animated { NSArray *array=self.tabBarController.view.su ...

  8. 自定义cell自适应高度

    UITableView在许多App种被大量的应用着,呈现出现的效果也是多种多样的,不能局限于系统的一种样式,所以需要自定义cell 自定义cell呈现的内容也是多种多样的,内容有多有少,所以需要一种能 ...

  9. IOS开发-cell的动态高度

    tableView中自定义cell的高度随子控件的内容动态变化,也是用的非常多的地方.现在就来处理一个自定义一个里面有文字(多少不定),图片(有无不定)的cell 首先要准备两个模型,一个是存放数据的 ...

随机推荐

  1. 射频识别技术漫谈(26)——Felica的文件系统

    Felica的文件系统使用“系统\域\服务\数据块”的结构,如下图所示.通过这种结构实现对卡片非易失性存储区的使用和操作.                                     Fe ...

  2. S50卡

    产品名称:Mifare 1K(S50)卡 芯片类型:Philips Mifare 1 IC S50 存储容量:8Kbit,16个分区,每分区两组密码 工作频率:13.56 MHz 通讯速率:106KB ...

  3. Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock(转)

    本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...

  4. 如何使用 Barracuda 防火墙设置/保护 Azure 应用程序

     如果某企业在 Windows Azure 上托管某个应用程序,该应用程序会在某个特定时间暴露到 Internet,以用于商业用途.公共 Internet 带来 客户的同时也带来了攻击者. Tim ...

  5. VS2010/MFC说明

    此栏目大多数内容转自鸡啄米http://www.jizhuomi.com/ 方便使用对其内容做了少量修改,仅是个人收藏使用,不做其它用途.

  6. B - 楼下水题(扩展欧几里德)

    B - 楼下水题 Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit St ...

  7. Live Writer Test

    测试下LiveWriter写CNblog: 1.Source code plug-in: @Override public List getAll(String orgid,String start, ...

  8. Visual Studio Tip: Get Public Key Token for a Strong Named Assembly

    The first 3 parts are easy to get. I should know the name, version, and culture for the assembly sin ...

  9. 在SQL 中生成JSON数据

    这段时间接手一个数据操作记录的功能,刚拿到手上的时候打算用EF做,后来经过仔细考虑最后还是觉定放弃,最后思考再三决定: 1.以模块为单位分表.列固定(其实可以所有的操作记录都放到同一个表,但是考虑到数 ...

  10. iOS开发常识

    一.NSString 创建字符串.  NSString *astring = @"This is a String!"; 创建空字符串,给予赋值.  NSString *astri ...