UINavigationController在ios7的变化

   最近做了个关于UINavigationController的demo,遇到一个问题,又引出更多问题,记录一下。 在ios7中,UINavigationController发生了很大的变化,特别是导航栏。

   先用一些代码,描述问题

  1、添加导航控制器和视图控制器:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    MainViewController* mainController = [[MainViewController alloc] init];
    UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:mainController];
    self.window.rootViewController = nav;
    return YES;
<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

  2、MainViewController添加UILabel

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0,0, 50, 50)];
    [label setText:@"test"];
    [label setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:label];
}

代码在ios6和ios7运行的效果如下:

ios6:

ios7:


描述:self.view代表maincontroller的视图

问题出现了,很明显可以看出来,在ios7里面,self.view的内容延伸到了导航栏和状态栏的下面,并且可以模糊的看到。

首先我们来大概了解一下导航器的视图结构。用NSLog打印出状态栏、导航条和self.view以及self.view.superview的frame可以看出一些来。这里以3.5屏幕为例:

在ios6中:                         状态栏(0,0,320,20)    导航条(0,20,320,44)   self.view(0,0,320,416)     self.view.superview(0,64,320,416)

ios6隐藏状态栏:              状态栏(0,0,0,0)          导航条(0,0,320,44)     self.view(0,0,320,436)     self.view.superview(0,44,320,436)

ios6隐藏导航栏:              状态栏(0,0,320,20)   导航条(0,-24,320,44)   self.view(0,0,320,460)     self.view.superview(0,20,320,460)

可以看出,状态栏、导航栏、self.view.superview在同一个坐标系内。状态栏和导航栏的改变,会影响self.view.superview的变化。但是要注意的是,self.view的坐标始终不变,只是高度会随着superview而变化。至于隐藏导航栏以后,为什么y坐标会变为-24,是因为作为状态栏的背景吗?


在ios7中,状态栏背景透明,导航栏半透明,导航栏的背景高度为64,坐标(0,-20,320,44),Y方向多出的20点可以作为状态栏的背景。默认self.view延伸到屏幕顶部,被状态栏和导航栏覆盖。默认导航栏的 translucent = YES  此时各个元素的frame如下:

                                         状态栏(0,0,320,20)    导航条(0,20,320,44)   self.view(0,0,320,480)     self.view.superview(0,0,320,480)

ios7隐藏状态栏:              状态栏(0,0,0,0)          导航条(0,0,320,44)     self.view(0,0,320,480)     self.view.superview(0,0,320,480)

ios7隐藏导航栏:              状态栏(0,0,320,20)   导航条(0,-44,320,44)   self.view(0,0,320,480)     self.view.superview(0,0,320,480)

可以看出,self.view.superview不会因为状态栏和导航栏的改变而发生变化,始终铺满整个屏幕,当然self.view也是铺满整个屏幕的。

现在设置translucent = NO  

                状态栏(0,0,320,20)    导航条(0,20,320,44)   self.view(0,64,320,416)     self.view.superview(0,0,320,480)

ios7隐藏状态栏:      状态栏(0,0,0,0)      导航条(0,0,320,44)     self.view(0,44,320,436)     self.view.superview(0,0,320,480)

ios7隐藏导航栏:      状态栏(0,0,320,20)   导航条(0,-44,320,44)   self.view(0,0,320,480)      self.view.superview(0,0,320,480)

设置translucent=NO之后,self.view.superview依然铺满屏幕,而self.view在状态栏和导航栏都可见的情况下,Y方向坐标是64;当状态栏隐藏,self.viewY坐标上移20点,高度增加20点。这是因为设置了导航栏的属性translucent=NO,所以self.view从导航栏下面开始平铺。

重点是,隐藏了导航栏之后,translucent属性失去作用,self.view从屏幕左上角开始平铺,被状态栏覆盖了20点的高度。

总结:

一、ios6中

1、状态栏20高度导航栏44高度;

2、self.view.superview的Y坐标和高度会随着状态栏和导航栏高度变化;

3、self.view坐标和宽度不变,高度会随着self.view.superview变化。self.view的子视图不会被状态条或者导航条遮盖。

二、ios7中

1、状态栏背景透明,高度20;

2、导航栏背景半透明,坐标(0,-20,320,64),Y轴方向多出的20点可以作为状态栏的背景,所以设置导航栏背景色,也能作为状态栏背景色;

3、因为状态栏和导航栏所在区域提供给开发者操作,所以self.view.superview从屏幕顶部开始平铺整个屏幕并且固定并不变;

4、当导航栏显示且透明时,self.view的坐标(0,0),当然也是平铺整个屏幕,延伸到导航栏和状态栏下面;

5、当导航栏显示但是不透明,self.view刚好在导航栏的下边界开始平铺,此时状态栏的隐藏会影响到导航栏和self.view的坐标和高度。

6、导航栏隐藏,则透明属性不起作用,self.view坐标(0,0),平铺整个屏幕,延伸到状态栏的下面。

三、对于ios7中设置self.view从导航栏下面显示,有三种方式

1、[self setEdgesForExtendedLayout:UIRectEdgeNone]; 设置本控制器的视图延伸范围。对本控制器视图有效果。

在ios7以下ios3以上的系统,可以使用wantsFullScreenLayout属性代替。

2、[navigationBar setTranslucent:NO]; 设置导航栏不透明,对所有控制器视图有效果。导航栏不透明了,不会再让你延伸view了。

3、[navigationBar setBackgroundImage:[UIImage imageNamed:@"image_background.png"] forBarMetrics:UIBarMetricsDefault];自定义导航栏背景图片,对所有控制器视图有效果。自定义背景,等于不透明,延伸了也看不到哇。 

iOS7 SDK中新增了一个设置背景图片的方法(setBackgroundImage:forBarPosition:barMetrics:),比原有的方法多了一个UIBarPosition枚举参数,用于设置背景图片拉伸的策略

UIBarPositionTopAttached表明操作栏贴近屏幕顶部,背景向上延伸入系统状态栏区域。相对的,值UIBarPositionTop表示操作栏位于当前局部内容的顶部(比如,在弹出式气泡的顶部)它不为状态栏提供背景

所以可以判断ios版本,用不同API给导航栏设置背景图片,来达到适配ios7和ios6的目的

在2和3的case,可以单独设置某个控制器view延伸到导航栏和状态栏下面:extendedLayoutIncludesOpaqueBars属性,默认是NO,设置为YES时,可以延伸。

知晓了以上的情况,在设置self.view的布局及其子视图的时候,就可以根据需求来设置了。


理解不够深刻和准确,非常欢迎指正!

后面转载一篇更加专业的博文。

//6月11日更新

总结中case3里面,背景图片如果是半透明的,self.view还是会有延伸效果的;所以如果想阻挡它的延伸,一定要是不透明的背景图片。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值