iOS 导航栏

最近项目里有个需求和导航栏的样式定制有关,深入之后发现之前理解的一些概念有些模糊,刚好趁着这次机会全面整理了一下。

从 iOS7 开始,苹果采用了大量的扁平化和毛玻璃风格,刚升级到 iOS7 之后会发现界面的布局多多少少有一些偏差(当然现在新建的项目没有这方面困扰,不需要经历6到7的适配),适配过程中会发现如下一些属性,

- edgesForExtendedLayout

- translucent

- extendedLayoutIncludesOpaqueBars

- automaticallyAdjustsScrollViewInsets

根据字面意思看上去这些属性很好理解,但是发现他们组合之后会有一些不同的表现,一些奇怪的问题也不知道什么原因导致的。不用担心,接下去我会全面的解析一下这几个属性的含义,保证你再也不怕各种奇怪的导航栏问题啦。

edgesForExtendedLayout + translucent

iOS7 以后,edgesForExtendedLayout 的默认设置是 UIRectEdgeAll,translucent 的默认值是 true。这种组合会使 rootView 的布局从(0,0)开始,即 view 的内容会被导航栏遮挡住,大多数情况下将 edgesForExtendedLayout 修改为 UIRectEdgeNone 就能解决布局被遮挡的问题。将 translucent 设置成 false 也会使 rootView 从导航栏底部开始,但是 translucent = false 时即使将 edgesForExtendedLayout 再改成 UIRectEdgeAll rootView 还是从导航栏底部开始布局。如何可以在导航栏不透明的情况下让 rootView 从(0,0)开始布局呢?苹果也考虑到了这种需求,提供了 extendedLayoutIncludesOpaqueBars 这个属性。

小结:translucent 为 true,rootView 从(0,0)开始布局,修改 edgesForExtendedLayout 属性可以改变布局;translucent 为 false,rootView 从导航栏底部开始布局,修改 edgesForExtendedLayout 属性无法改变布局。

extendedLayoutIncludesOpaqueBars + translucent

前面我们知道了 translucent 为 false 时,修改 edgesForExtendedLayout 也无法使 rootView 从(0,0)开始布局。苹果为此提供了 extendedLayoutIncludesOpaqueBars,字面上理解的意思就是在不透明的导航栏下也全屏显示。

这里多提一点,在 ViewController 的生命周期中有 viewDidLoad,viewWillAppear,viewDidAppear,viewWillDisappear,viewDidDisappear,上述提到的这些属性需要在 viewDidAppear 之前设置好,viewDidAppear 可以认为系统已经根据配置布局好了,在这里展示给用户看。

automaticallyAdjustsScrollViewInsets

automaticallyAdjustsScrollViewInsets 默认值是 true,表示在全屏模式下会自动修改第一个添加到 rootView 的 scrollview 的 contentInset 为(64,0,0,0),这样 scrollview 就不会被导航栏遮挡了。

关于 scrollview 有一个问题比较常见,这里解析一下原因。我们经常会这么使用一个 tableView,

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view.

self.view.backgroundColor = [UIColor greenColor];

self.navigationItem.title = @"Master";

self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];

_tableView.backgroundColor = [UIColor whiteColor];

_tableView.delegate = self;

_tableView.dataSource = self;

[self.view addSubview:_tableView];

}

这样在默认情况下(translucent = true, edgesForExtendedLayout = UIRectEdgeAll),tableView的显示没有问题。但是当我们将 edgesForExtendedLayout 设置成 UIRectEdgeNone 时,当 tableView 的内容比较多时底部的内容反而显示不下。这就很奇怪了,按照前面的结论,这时候 tableView是从导航栏底部开始布局的,contentInset 也是(0,0,0,0),怎么底部的内容会被遮挡一部分呢?原因在于 self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds]; 初始化时 rootView 的 frame 还是(0,0,screenWidth,screenHeight),只需要在 viewWillLayoutSubviews 中重新修改一下 tableview 的 frame 即可,

- (void)viewWillLayoutSubviews

{

[super viewWillLayoutSubviews];

_tableView.frame = self.view.bounds;

}

UINavigationBar 修改背景色

UINavigationBar 是 UIView 的子类,首先想到的是修改背景色,

self.navigationController.navigationBar.backgroundColor = [UIColor greenColor];

发现这并不是我们想要的效果,为什么绿色变淡了呢?通过 Xcode 的 ViewDebugging 我们可以看到 UINavigationBar 内部还有一些子视图,这些子视图的背景色会遮挡住我们设置的颜色。

查看 UINavigationBar 的接口我们发现 setBackgroundImage,设置

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor greenColor] size:CGSizeMake(1, 1)] forBarMetrics:UIBarMetricsDefault];

结果如下

小结:设置 UINavigationBar 的 backgroundImage 可以修改导航栏的背景色。

translucent 和 setBackgroundImage

前面提到我们可以通过修改背景图片来修改导航栏的背景色,设置了背景图片后在有些页面我们会遇到一些奇怪的问题,发现原来布局正常的页面显示不对了,会多出一部分空白或者被导航栏遮挡住了。

通过打印出 translucent 的值我们发现设置了纯色的背景图后原来半透明的导航栏变成了不透明的,结合前面提到的 translucent 对布局起点的影响,如果页面是按照半透明情况,即 rootView 从(0,0)开始布局来设置子视图的 frame,那么设置了纯色背景图后 translucent 变成了 false,即 rootView 从(0,64)开始布局。为什么设置背景图片会影响 translucent 呢,通过查看文档发现了如下说明,

/*

New behavior on iOS 7.

Default is YES.

You may force an opaque background by setting the property to NO.

If the navigation bar has a custom background image, the default is inferred

from the alpha values of the image—YES if it has any pixel with alpha

也就是说背景图片如果包含 alpha 的色值,系统会默认将 translucent 设置为 true,没有包含 alpha 色值会将 translucent 设置为 false。这下真相大白了,原来我们前面设置了纯绿色的背景图片,是不包含 alpha 色值的,即系统默认将 translucent 设置成了 false。但这是针对没有手动设置 translucent 值的情况,如果我们手动设置了 translucent,那么系统就不会根据背景图片的 alpha 来修改 translucent。

至此,我们了解了苹果是如何使用这几个属性的,针对 iOS7 以上,这里做一下总结:

    1. iOS7 以后 translucent 默认为 true,rootView 从(0,0)开始布局,修改 edgesForExtendedLayout 属性可以改变布局;
    2. translucent 为 false,rootView 从导航栏底部开始布局,修改 edgesForExtendedLayout 属性无法改变布局,可以通过设置 extendedLayoutIncludesOpaqueBars 从(0,0)开始布局;
    3. automaticallyAdjustsScrollViewInsets 默认值是 true,表示在全屏模式下会自动修改第一个添加到 rootView 的 scrollview 的 contentInset 为(64,0,0,0),用来纠正scrollview在全屏模式下的显示;
    4. 设置 UINavigationBar 的背景图片可以改变导航栏背景色,如果背景图片包含 alpha 的色值,系统会默认将 translucent 设置为 true,没有包含 alpha 色值会将 translucent 设置为 false。但这是针对没有手动设置 translucent 值的情况,如果我们手动设置了 translucent,那么系统就不会根据背景图片的 alpha 来修改 translucent。
时间: 2024-10-02 06:38:19

iOS 导航栏的相关文章

iOS 导航栏的属性设置

iOS中设置导航栏背景.字体属性 --------------------------------------------------- 1.自定义导航控制器作为基类,在 + (void)initialize 方法中设置偏好设置,不要在 + (void)load 方法中设置 + (void)initialize { // 设置 两侧按钮 的颜色tintColor(标题除外) [[UINavigationBar appearance] setTintColor:FGCOLOR]; // FGCOL

iOS 导航栏黑线,UIImage 枚举处理方式

ios 找出导航栏下面的黑线(可隐藏,改变样式等) http://www.jianshu.com/p/effa4a48f1e3 设置UIImage的渲染模式:UIImage.renderingMode http://blog.csdn.net/djxiaoyu_haha/article/details/40949083 着色(Tint Color)是iOS7界面中的一个.设置UIImage的渲染模式:UIImage.renderingMode重大改变,你可以设置一个UIImage在渲染时是否使用

自定义iOS导航栏背景,标题和返回按钮文字颜色-----转载自gyz413977349

在iOS7下,默认导航栏背景,颜色是这样的,接下来我们就进行自定义,如果你仅仅是更改一下背景和颜色,代码会很简单,不需要很复杂的自定义View来替代leftBarItem 更改导航栏的背景和文字Color 方法一: [objc] view plaincopy //set NavigationBar 背景颜色&title 颜色 [self.navigationController.navigationBar setBarTintColor:[UIColor colorWithRed:20/255.

转:ios导航栏设置

原帖:http://www.cocoachina.com/industry/20131104/7287.html 本文提供的代码需要用Xcode 5来执行.如果你还在使用老版本的Xcode,那么在运行示例之前请将Xcode升级到Xcode 5. iOS 7中默认的导航栏 在开始定制之前,我们先来看看iOS 7中默认导航栏的外观.通过Xcode用Single View Controller模板创建一个工程.然后将view controller嵌入到一个navigation controller中.

<iOS 导航栏>第一节:导航栏透明方法实现代码

说下导航栏的透明方法: 很多应用需要导航栏随着向上滑动,逐渐从透明变成不透明,很炫酷,大部分应用都在使用导航栏渐变效果,现附上代码然后直接将实现,一会讲下如何来实现,这一部分直接上代码. 先附上代码: 方法声明: #import <UIKit/UIKit.h> @interface IDSNavBarView : UIView - (instancetype)initWithFrame:(CGRect)frame titleImg:(UIImage *)aTitleImg; - (UILabe

ios 导航栏 点击barbutton的按钮 下拉列表

环境:xocde5.0.2+ios7.0.1 1.导航栏 ----点击科目--------下拉列表 代码:NGRightTableViewViewController.h #import <UIKit/UIKit.h> @protocol PulldownMenuDelegate -(void)menuItemSelected:(NSIndexPath *)indexPath; -(void)pullDownAnimated:(BOOL)open; @end @interface NGRigh

ios 导航栏(自己定义和使用系统方式)

系统方式: //1.设置导航栏背景图片 [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault]; self.navigationController.navigationBar.shadowImage = [[UIImage alloc]init]; [[self navigationController] setNa

IOS 导航栏颜色 标题

修改导航栏颜 1 #define COLOR_TOMATO    [UIColor colorWithRed:255/255.0f green:99/255.0f blue:71/255.0f alpha:1.0f]     /*!< 番茄色 */ 2 3 self.navigationController.navigationBar.barTintColor = COLOR_TOMATO;//修改导航栏颜色 修改导航栏标题字体(大小.颜色) 1 self.navigationControlle

iOS:导航栏的工具条和导航条

// // main.m // Hello // // Created by lishujun on 14-8-28. // Copyright (c) 2014年 lishujun. All rights reserved. // #import <UIKit/UIKit.h> @interface TestViewController : UIViewController @end @implementation TestViewController -(void) loadView {