欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UINavigationBar和UINavigationItem

程序员文章站 2024-03-24 13:20:52
...

今天修复了一个小bug, 由于一个viewController的右边有3个按钮,在手机上和中间的title离得有点近了. 大致是这样 , 按钮是随便写的 , 没加图????,

UINavigationBar和UINavigationItem
通过这样设置的 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView: rightView]; rightView是一个普通的UIView,上面放了3个button , 
既然右边按钮距离中间的title太近了, 而且 "更多" 右边还有一点小空隙 , 就想改变rightBarButtonItem距离右边的距离,让3个按钮往右挤挤,大致是做成这样的.
UINavigationBar和UINavigationItem

好了, 现在知道了现状,也知道的目的.那就开始做了.


一开始的想法是 通过加一个UIBarButtonSystemItemFixedSpace的item,把这个设置为负值,这样就可以把rightView右移了, 代码大致是这样


UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]   
                               initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace   
                                   target:nil action:nil];  
/**  
 *  width为负数时,相当于btn向右移动width数值个像素,由于按钮本身和边界间距为5pix,所以width设为-5时,间距正好调整  
 *  为0;width为正数时,正好相反,相当于往左移动width数值个像素  
 */  
negativeSpacer.width = -5;  
self.navigationItem.rightBarButtonItems = @[negativeSpacer, rightView, ];  

可惜,理想很美好,现实很骨感, 把 negativeSpacer.width 设置成一个正值倒是挺管用的 ; 设置为-20, 一点变化也没有 , 估计是在iOS的某次更新后系统做了处理了 , 好吧,下一条路.


第二种思路 ,  UIBarButtonItem 里面的文档看了好久 , UIBarButtonItem都不是UIView的子类 , 没有可以设置边距的东西 ,   后面甚至想到了重写 navigationController的viewDidLayoutSubviews , 在那里面重写设置frame, 但是想想这个影响的页面太多了,判断会很多 , 也不太能拿到 这个rightView ,  得不偿失.

就在失望之际 , 发现了UINavigationBar *navigationBar , 这是UIView的一个子类, 或许可以在这个上面动动手脚 , 于是 

    UIView * rightView =  [[UIView alloc] initWithFrame:CGRectMake(Screen_Width-130, 0, 130, 44)];
    [rightView addSubview:videoButton];
    [rightView addSubview:micButton];
    [rightView addSubview:moreBtn];
   
    [self.navigationController.navigationBar addSubview:rightView];

运行之后 , 果然变成了想要的样子. 右边贴边了 , 而且想设置多少就是多少, 美滋滋.

UINavigationBar和UINavigationItem

但是在pop的时候发现了一个问题 , 已经pop到上一个界面了, 但是这3个按钮没有消失 , 只要将信将疑的在viewWillDisappear里 , 把[rightView removeFromSuperview] , 事实果然有效, pop之后, 这3个按钮也消失了. nice.


虽然功能完成了,但是UINavigationBar和UINavigationItem是什么关系呢? 自然要一探究竟.

一、导航条navigation bar

1、导航条navigationbar属于导航控制器,一个导航控制器只有一个导航条。

2、在一个导航控制器push新页面和pop页面时,导航条是同一个。

3、在一个视图控制器内改变了导航条的样式,其它控制器的导航条的样式也会改变,也说明了导航条属于导航控制器,而不是每个视图控制器都有一个导航条。

4、导航条的层级结构

navigationbar层级

 

UINavigationBar和UINavigationItem

 

UINavigationBar和UINavigationItem

UINavigationBar

 

UINavigationBar和UINavigationItem

UIBarBackground

UIBarBackground视图是比UINavigationBar视图要大

二、导航栏与self.view布局问题

iOS开发过程当中遇到导航栏遮挡布局的问题,在页面跳转后,下级页面也会被导航栏所遮挡。

如果你的容器是UINavigationController,在iOS7之前导航栏默认为半透明的,布局默认会从顶部开始,所以会被遮挡。

解决方案1:

在iOS7 UIViewController引入了一个新的属性edgesForExtendedLayout,默认为UIRectEdgeAll,即铺满整个屏幕

self.edgesForExtendedLayout =UIRectEdgeNone;设置后布局从导航栏下开始

解决方案2:

self.navigationController.navigationBar.translucent =NO;

将导航栏设置为不透明后,布局会自动放到导航栏以下。

三、导航栏与self.view高度问题

在带有导航栏的控制器中,viewDidLoad方法执行前后self.view的高度是不一致的,执行前为屏幕的高度,而执行后则减去导航栏+状态栏的高度。

//以iphone6为例

- (void)viewDidLoad {

[super viewDidLoad];

NSLog(@"执行前%d",CGRectGetHeight(self.view.frame));

}

- (void)viewDidAppear:(BOOL) animated{

[super viewDidLoad];

NSLog(@"执行后%d",CGRectGetHeight(self.view.frame));

}

log:

执行前667

执行前603

准确说应该是viewWillAppear和viewDidAppear之间self.view高度发生变化

在viewWillAppear时视图控件布局还没有设置,因此对于一个VC,self.view就是最原始的状态,从屏幕顶端开始,高度为ScreenHeight

在viewDidAppear时视图已经显示在屏幕上了,self.view以及子视图的布局已经设置好了,而self.view由于导航栏不透明或其他原因,其布局是从导航栏下方开始到屏幕底部,高度为ScreenHeight-64,64为导航栏(44)+状态栏(20)高度

四、navigationBar与navigationItem

1、navigationbar继承自UIView,通常是位于屏幕顶端的控件。

2、navigationbar是navigationitem的容器,以stack的形式管理UINavigationitem。需要说明的是UInavigationbar属于导航控制器,且只有一个,navigationitem是独立存在的不属于导航控制器也不属于导航条,它是视图控制器的属性,每一个viewController都有一个navigationitem。navigationbar提供了多种方法来管理单个和多个navitionItem。

3、UINavigationitem也是容器。包括titleView 、左侧N个UIBarButtonItem,右侧N个UIBarButtonItem这些控件,并提供了方法来管理这些控件。

总结 , navigationBar与navigationItem关系 ,  可以类比 navigationController 与 viewcontroller, 
navigationItem 与 titleView , leftBarButtonItem 的关系, 可以类比 self.view 与 view上的子控件 .

NSLog(@"topItem  %@",self.navigationController.navigationBar.topItem);
NSLog(@"items  %@",self.navigationController.navigationBar.items);

topItem  <UINavigationItem: 0x102865e80> title='订单详情' leftBarButtonItems=0x2803a00f0
items  [
	第0个 -- <UINavigationItem: 0x102808640> title='热门' titleView=0x101f4d400 
	第1个 -- <UINavigationItem: 0x1028ccb00> title='项目订单' leftBarButtonItems=0x2803aa430 
	第2个 -- <UINavigationItem: 0x102865e80> title='订单详情' leftBarButtonItems=0x2803a00f0

https://www.jianshu.com/p/a7d5078e31db

 

相关标签: UI相关