去掉ios7的全屏布局

简介: 去掉ios7的全屏布局 (2014-03-10 19:58:45)转载▼  前言iOS7是目前iOS史上最颠覆的一次改版。它的出现令人兴奋,因为它将会带我们进入一个全新的时代;它的到来也让我们忧心,因为它颠覆了一切,包括我们过去做过的很多努力。

去掉ios7的全屏布局

  (2014-03-10 19:58:45)
   

前言

iOS7是目前iOS史上最颠覆的一次改版。
它的出现令人兴奋,因为它将会带我们进入一个全新的时代;
它的到来也让我们忧心,因为它颠覆了一切,包括我们过去做过的很多努力。
但是,相信大家乐意为这个全新时代做更多的努力,因为,它值得期待。
 
最近打算写一系列针对iOS7新特性的文章,今天就从最基本和简单的页面布局开始吧。
 
 

从头说起

当我看见iOS7那个半透明设计的navigationBar,已经有种不详的预感。
因为要透过navigationBar看到底下滚动的内容,那么底下的内容必须从顶部开始布局,并且需要设定相应的内边距以让初始内容显示在合适的位置上。
要对应用适配这种凶残设计,其工作量绝比适配iPhone5屏幕还要多许多。
 
我马上翻了一下iOS7相关的文档,在《iOS 7 UI Transition Guide》的 Bar and Bar Buttons一节中得到了证实 ——
 
In iOS 7, the status bar is transparent, and other bars—that is, navigation bars, tab bars, toolbars, search bars, and scope bars—are translucent. As a general rule, you want to make sure that content fills the area behind the bars in your app.
在iOS7中,状态栏是完全透明的,而其他bar,即navigation bars, tab bars, toolbars, search bars和scope bars都是半透明的。开发者需要保证页面内容能覆盖到这些bar的后面。
 
事实上,iOS7中的状态栏不仅变完全透明了,而且完全不占空间。
有码有真相 —— 新建一个UIViewController,再viewDidLoad里面输入以下代码,作为rootViewController启动应用:
01 - (void)viewDidLoad
02 {
03     [super viewDidLoad];
04      
05     self.view.backgroundColor = [UIColor whiteColor];
06      
07     UILabel *label = [[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 20)]autorelease];
08     label.text = @"I am a label";
09     [self.view addSubview:label];
10 }
 
应用效果:
可以看到的是label和status bar悲催地重叠了。
我们再套一个UINavigationController,可以看到更悲催的事情:
 
label活生生地被navigationBar盖住了。
 
可以说,苹果这次在iOS7上的redesign对开发者来说是惨绝人寰的。
不过苹果还是有节操的,在iOS7上运行iOS7 SDK以下开发的应用时,保留了原先的页面结构布局,并且做了不少向下兼容策略。
而且,iOS7 SDK提供了一系列接口和策略方案,下文将会一一介绍并顺带剖析一下iOS7上的页面结构框架。
 
 

Realtime Debug Protal

在讨论如何应对凶残的iOS7之前,我首先介绍一个自己之前捣腾的小工具,可以方便我们进行学习。
它的小名叫RDP,是一个类似Web Inspector的工具,把这个工具引入我们的项目工程,并做一些简单的配置,然后运行真机或者模拟器。
应用启动后,在浏览器输入手机的IP地址,就可以看到UIView的树状结构和Log信息,还可以在浏览器中对View进行移动,隐藏,选中高亮等操作。
 
 
这是iOS7上面的页面结构,对比一下iOS6和iOS5的,就这样已经可以看出区别来了。
 
 
 
不过今天的重点不是横向对比,而是在iOS7上的纵向对比,请看下文。
 
 

状态栏

在iOS7中,状态栏是透明的,就是说,状态栏只有文字没有背景。
这个改动让我颇为意外,因为一直印象中苹果很care状态栏的,之前也曾听说过有应用因为遮挡了状态栏而被Appstore拒绝。
而且苹果之前状态栏提供的三种样式都是以深色底白色字呈现,保证了状态栏的内容清晰易读。
 
而变透明之后就很容易和后面的内容混淆,虽说一般应用不会把内容和状态栏叠合在一起,但是至少,现在的情况是,默认是会叠合的,开发需要从20px像素以下开始布局页面元素才能避免。
 
苹果为了让深色浅色背景均能让状态栏内容清晰显示,提供两种状态栏样式:
 
UIStatusBarStyleDefault = 0 黑色文字,浅色背景时使用
UIStatusBarStyleLightCon tent = 1 白色文字,深色背景时使用
 
而以下两个旧状态栏样式将被废弃:
UIStatusBarStyleBlackTra nslucent = 1
UIStatusBarStyleLightCon tent = 2
 
还有,iOS7中我们通过ViewController重载方法返回枚举值的方法来控制状态栏的隐藏和样式。
首先,需要在Info.plist配置文件中,增加键: UIViewControllerBasedStatusBarAppearance,并设置为YES;
然后,在UIViewController子类中实现以下两个方法:
1 - (UIStatusBarStyle)preferredStatusBarStyle
2 {
3     return UIStatusBarStyleLightContent;
4 }
5  
6 - (BOOL)prefersStatusBarHidden
7 {
8     return NO;
9 }
 
最后,在需要刷新状态栏样式的时候,调用[self setNeedsStatusBarAppeara nceUpdate]方法即可刷新,若果需要以动画形式切换状态栏样式,则用以下方式调用即可:
 
1 [UIView animateWithDuration:0. animations:^{
2     [self setNeedsStatusBarAppearanceUpdate];
3 }];
 
 

导航栏

在iOS7,由于状态栏背景透明,那么,导航栏背景就可能要兼职充当状态栏背景了。
iOS7默认导航栏样式就是这么做的,见下图:
 
 
虽然用户看来,iOS7默认样式的状态栏和导航栏时连在一起的,但是实际上导航栏的位置和大小是和之前系统版本一样的,依然是贴在状态栏下面,依然是高44px;之所以用户看来它们是连在一起,这是因为UINavigationBar里面的_UINavigationBarBackgroun d定位在y方向-20px的位置,然后高度增加到64px,这样就可以同时充当了两者的背景。
 
关于这些定位,苹果做了很多工作,后面也会谈到不少。不关心的同学可以略过,其实这些细节,个人觉得,即使对于开发者来说,也不是必需知道的,我们只需要知道怎么调用相关API就足够了。
实际情况下,我们会自定义导航栏背景,过去,我们也许会使用如下代码把一张高44像素(retina/88像素)的图片来平铺作为导航栏背景。
 
1 [navCtrl.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_background"] forBarMetrics:UIBarMetricsDefault];
 
启动应用,出现了意想不到的效果和久违的界面 —— 黑底白字的状态栏,不再被navigationBar盖住的label。
 
 
这里两个点需要解释一下:
 
  1. 若我们使用自定义图片作为导航栏的背景,那么UIViewController的view(下面称为视图)就不会延伸到navigationBar的顶部,而是从它的底部开始——正如往常一样。
  2. 若我们使用一张高44像素(retina/88像素)的图片作为导航栏背景,那么状态栏就会保持黑色,图片只会在导航栏区域平铺。
 
另外,iOS7 SDK中新增了一个设置背景图片的方法(setBackgroundImage:forBarPosition:barMetrics:),比原有的方法多了一个UIBarPosition枚举参数,用于设置背景图片拉伸的策略。
针对不同的拉伸设置和背景图片尺寸,在《iOS 7 UI Transition Guide》的 Bar and Bar Buttons一节中
中有详细说明:
 
 
PS:原文中的"resize"翻译为“调整”,表述比较含糊,根据实际操作结果看,水平方向调整一般是平铺,垂直方向调整一般是局部拉伸。
 
 

页面布局

在 《iOS 7 UI Transition Guide》的 Layout and Appearance  一节中也提到 —— 在iOS7中,view controllers使用全屏布局 (In iOS 7, view controllers use full-screen layout)。
 
通过上面的讨论我们也知道,除非导航栏设置了自定义的背景图片,否则每个视图都会延伸到屏幕一样大小的。
所以,像上面第二张图片中出现导航栏遮盖label的情况也是正常的现象。
 
如果我们要让label从导航栏以下位置显示,可以通过修改UIViewController的 edgesForExtendedLayout这个属性来实现。
edgesForExtendedLayout是一个类型为UIExtendedEdge的属性,指定边缘要延伸的方向。
因为iOS7鼓励全屏布局,它的默认值很自然地是UIRectEdgeAll,四周边缘均延伸,就是说,如果即使视图中上有navigationBar,下有tabBar,那么视图仍会延伸覆盖到四周的区域。
 
如果把视图做如下设置,那么视图就不会延伸到这些bar的后面了,于是label又出来了。
1 self.edgesForExtendedLayout = UIExtendedEdgeNone;
 
 
 
也许,这时候你会想,那为什么不把UIExtendedEdgeNone作为默认态呢?
iOS7鼓励全屏,它希望用户在使用可滚动视图的时候可以透过半透明的bar还可以看到一些模模糊糊的内容。
 
为了保持设计的优雅,同时避免给开发者太多的困扰,iOS7在Conttoller中新增了这个属性: automaticallyAdjustsScrollViewInsets,当设置为YES时(默认YES),如果视图里面存在唯一一个UIScrollView或其子类View,那么它会自动设置相应的内边距,这样可以让scroll占据整个视图,又不会让导航栏遮盖,如以下例子:
 
 
 
要注意的是,这个例子中我们没有设置edgesForExtendedLayout,即视图是延伸至全屏的。
我们可以从UIView树状图看到,tableview的bounds值中有64像素的偏移值,它作为一个内边距来保持内容显示在导航栏以下,而滚动时仍可以透过半透明的导航栏看到模糊的内容。
 
最后一个介绍的新属性是 extendedLayoutIncludesOpaqueBars,这个属性指定了当Bar使用了不透明图片时,视图是否延伸至Bar所在区域,默认值时NO。
所以我们如果自定义了导航栏的背景图片,那么视图会从导航栏以下开始,不会延伸到导航栏区域。
如果把这个属性设置为YES,那么视图将会延伸至导航栏区域,即使我们把导航栏设置成了自定义背景,如下图:
 
 
 
视图延伸之后,label又被导航栏覆盖住了,正如我们意料。
 
好了,这次就介绍到这里了。
下次我们讨论一下如何写兼容iOS7和iOS5、6的页面布局。
self.edgesForExtendedLayout = UIRectEdgeNone; self.automaticallyAdjustsScrollViewInsets =NO;

OR

self.edgesForExtendedLayout = UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars =YES;
目录
相关文章
|
22天前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
83 1
|
29天前
|
设计模式 安全 Swift
探索iOS开发:打造你的第一个天气应用
【9月更文挑战第36天】在这篇文章中,我们将一起踏上iOS开发的旅程,从零开始构建一个简单的天气应用。文章将通过通俗易懂的语言,引导你理解iOS开发的基本概念,掌握Swift语言的核心语法,并逐步实现一个具有实际功能的天气应用。我们将遵循“学中做,做中学”的原则,让理论知识和实践操作紧密结合,确保学习过程既高效又有趣。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你打开一扇通往iOS开发世界的大门。
|
30天前
|
搜索推荐 IDE API
打造个性化天气应用:iOS开发之旅
【9月更文挑战第35天】在这篇文章中,我们将一起踏上iOS开发的旅程,通过创建一个个性化的天气应用来探索Swift编程语言的魅力和iOS平台的强大功能。无论你是编程新手还是希望扩展你的技能集,这个项目都将为你提供实战经验,帮助你理解从构思到实现一个应用的全过程。让我们开始吧,构建你自己的天气应用,探索更多可能!
52 1
|
2月前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
2月前
|
开发框架 数据可视化 Java
iOS开发-SwiftUI简介
iOS开发-SwiftUI简介
|
3天前
|
安全 API Swift
探索iOS开发中的Swift语言之美
【10月更文挑战第23天】在数字时代的浪潮中,iOS开发如同一艘航船,而Swift语言则是推动这艘船前进的风帆。本文将带你领略Swift的独特魅力,从语法到设计哲学,再到实际应用案例,我们将一步步深入这个现代编程语言的世界。你将发现,Swift不仅仅是一种编程语言,它是苹果生态系统中的一个创新工具,它让iOS开发变得更加高效、安全和有趣。让我们一起启航,探索Swift的奥秘,感受编程的乐趣。
|
5天前
|
Swift iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】在苹果生态系统中,SwiftUI的引入无疑为iOS应用开发带来了革命性的变化。本文将通过深入浅出的方式,带领读者了解SwiftUI的基本概念、核心优势以及如何在实际项目中运用这一框架。我们将从一个简单的例子开始,逐步深入到更复杂的应用场景,让初学者能够快速上手,同时也为有经验的开发者提供一些深度使用的技巧和策略。
19 1
|
22天前
|
移动开发 前端开发 Swift
iOS 最好的应用程序开发编程语言竟然是这7种
iOS 最好的应用程序开发编程语言竟然是这7种
63 8
|
21天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
|
25天前
|
安全 Swift iOS开发
探索iOS开发中的Swift语言之美
在数字时代的浪潮中,移动应用已成为日常生活的延伸。本文将深入探讨iOS平台上的Swift编程语言,揭示其背后的设计哲学、语法特性以及如何利用Swift进行高效开发。我们将通过实际代码示例,展示Swift语言的强大功能和优雅简洁的编程风格,引导读者理解并运用Swift解决实际问题。