如何自定义NavigationBar的高度

2024-02-29 11:08

本文主要是介绍如何自定义NavigationBar的高度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

自定义高度的UINavigationBar

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

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

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

代码如下:

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的高度正确地发生变化,事情就这么愉快地解决了!等等,导航栏上的标题和返回按钮的位置却都贴到最下面了,如下图:

自定义高度NavigationBar后,标题全都错位了

为什么会是这样?发生了什么?我也不知道!但是现在很明显就是需要我们去调整这两个“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这个消息中再加上这么两句:

1
2

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

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

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

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

1

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

运行结果:

自定义NavigationBar的高度完成示意图

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

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

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

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属性来创建这个按钮,但是我找不到这个时机来调整执行上面这个消息。更准确的问题可能是,下图中的这个消息到底应该怎么用才能看到效果呢?

setBackButtonBackgroundVerticalPositionAdjustment

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

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

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

这篇关于如何自定义NavigationBar的高度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/758552

相关文章

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

添加自定义的CALayer

iOS开发UI篇—CAlayer(创建图层) 一、添加一个图层 添加图层的步骤: 1.创建layer 2.设置layer的属性(设置了颜色,bounds才能显示出来) 3.将layer添加到界面上(控制器view的layer上)  1 // 2 // YYViewController.m 3 // 01-创建一个简单的图层 4 // 5 //

android自定义View的和FramgentActivity的一个小坑

对于自定义View //加载样式TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TitleBarView, defStyleAttr, 0);setTitle(typedArray.getString(R.styleable.TitleBarView_main_title));//不能写成

第三十七章 添加和使用自定义标题元素 - 自定义标头的继承

文章目录 第三十七章 添加和使用自定义标题元素 - 自定义标头的继承自定义标头的继承示例 在 `SOAPHEADERS` 参数中指定支持的标头元素自定义标头的继承 第三十七章 添加和使用自定义标题元素 - 自定义标头的继承 自定义标头的继承 如果创建此Web 服务的子类,该子类将继承不特定于方法的标头信息 — 包含在 <request> 或 <response> 元素中的标头信

QML 中宽度、高度与隐式宽度/高度的区别及其应用场景

在 QML 中,width、height 与 implicitWidth、implicitHeight 这几个属性常常令开发者感到困惑。本文将详细介绍它们之间的区别,并说明在何种情况下应使用隐式尺寸以及普通尺寸。 基本定义 width 和 height:表示组件/item 的实际尺寸。implicitWidth 和 implicitHeight:表示组件/item 的自然尺寸,即在未明确指定尺

游戏高度可配置化(一)通用数据引擎(data-e)及其在模块化游戏开发中的应用构想图解

游戏高度可配置化(一)通用数据引擎(data-e)及其在模块化游戏开发中的应用构想图解 码客 卢益贵 ygluu 关键词:游戏策划 可配置化 模块化配置 数据引擎 条件系统 红点系统 一、前言 在插件式模块化软件开发当中,既要模块高度独立(解耦)又要共享模块数据,最好的方法是有个中间平台(中间件)提供标准的接口来进行数据的交换,这在很多行业软件开发中已经广泛应用。但是,由于中间件的抽象和封

自定义recyclerView实现时光轴效果

时光轴效果在很多app上都有出现,例如淘宝中快递的跟踪,本文将使用recyclerView实现时光轴效果,我们会到自定义控件,首先先看一下效果图: 接下来是步骤分析 1自定义属性 这个大家应该都了解了,根据我们之前的分析,直接在attrs.xml中进行声明 <declare-styleable name="TimeLine"><attr name="beginLine" f

Android自定义系列——9.Path详细用法

rXxx方法 rXxx方法的坐标使用的是相对位置(基于当前点的位移),而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。 Path path = new Path();path.moveTo(100,100);path.lineTo(100,200);canvas.drawPath(path,mDeafultPaint); 在这个例子中,先移动点到坐标(100,100)处,之后再连接

Android自定义系列——8.Path之贝塞尔曲线

贝塞尔曲线能干什么 贝塞尔曲线作用十分广泛,简单举几个的栗子: QQ小红点拖拽效果一些炫酷的下拉刷新控件阅读软件的翻书效果一些平滑的折线图的制作很多炫酷的动画效果 理解贝塞尔曲线的原理 一阶曲线原理: 一阶曲线是没有控制点的,仅有两个数据点(A 和 B),最终动态过程如下: (本文中贝塞尔曲线相关的动态演示图片来自维基百科)。一阶曲线其实就是前面讲解过的lineTo。 二阶曲线