去掉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 黑色文字,浅色背景时使用
UIStatusBarStyleLightContent = 1 白色文字,深色背景时使用
 
而以下两个旧状态栏样式将被废弃:
UIStatusBarStyleBlackTranslucent = 1
UIStatusBarStyleLightContent = 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 setNeedsStatusBarAppearanceUpdate]方法即可刷新,若果需要以动画形式切换状态栏样式,则用以下方式调用即可:
 
1 [UIView animateWithDuration:0. animations:^{
2     [self setNeedsStatusBarAppearanceUpdate];
3 }];
 
 

导航栏

在iOS7,由于状态栏背景透明,那么,导航栏背景就可能要兼职充当状态栏背景了。
iOS7默认导航栏样式就是这么做的,见下图:
 
 
虽然用户看来,iOS7默认样式的状态栏和导航栏时连在一起的,但是实际上导航栏的位置和大小是和之前系统版本一样的,依然是贴在状态栏下面,依然是高44px;之所以用户看来它们是连在一起,这是因为UINavigationBar里面的_UINavigationBarBackground定位在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;
目录
相关文章
|
15天前
|
安全 Android开发 iOS开发
探索安卓与iOS开发的差异:平台特性与用户体验的深度对比
在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。本文旨在通过数据驱动的分析方法,深入探讨这两大操作系统在开发环境、用户界面设计及市场表现等方面的差异。引用最新的行业报告和科研数据,结合技术专家的观点,本文将提供对开发者和市场分析师均有价值的洞见。
|
5天前
|
Java Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【7月更文挑战第8天】在移动应用开发的广阔天地中,Android与iOS两大平台各自占据着半壁江山。本文将深入探讨这两个平台在开发环境、用户界面设计、性能优化以及市场覆盖等方面的根本差异,并分析这些差异如何影响项目的成功。通过比较和分析,旨在为开发者在选择平台时提供更全面的视角,帮助他们根据项目需求和目标市场做出更明智的决策。
|
18天前
|
Java 开发工具 Android开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
在移动应用开发的广阔天地中,Android和iOS两大平台各自占据着半壁江山。本文将深入探讨这两个平台在开发过程中的关键差异点,包括编程语言、开发工具、用户界面设计、性能优化以及市场覆盖等方面。通过对这些关键因素的比较分析,旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和目标受众做出明智的平台选择。
|
2天前
|
开发工具 Android开发 iOS开发
探索Android与iOS开发的差异与挑战
【7月更文挑战第11天】在移动应用开发的广阔天地中,Android和iOS两大平台如同双子星座般耀眼,各自拥有独特的开发生态和用户群体。本文将深入分析这两个平台的显著差异,从技术架构到开发工具,再到市场定位,揭示它们之间的异同。通过比较,我们不仅能够更好地理解各自的优势和局限,还能洞察未来移动应用开发的趋势。
|
6天前
|
开发工具 Swift iOS开发
探索iOS开发中的SwiftUI框架
【7月更文挑战第7天】在iOS应用开发的广阔天地中,SwiftUI框架以其现代化的设计理念和强大的功能特性,正逐步改变着开发者构建用户界面的方式。本文将深入探讨SwiftUI的核心概念、优势以及在实际项目中的应用,帮助读者理解这一框架如何简化iOS开发流程并提升用户体验。
187 7
|
5天前
|
移动开发 开发工具 Android开发
探索安卓与iOS开发的差异:平台特性与编程实践
【7月更文挑战第8天】在移动开发的广阔天地中,安卓和iOS这两大操作系统各自占据着半壁江山。它们在用户界面设计、系统架构及开发工具上展现出截然不同的特色。本文将深入探讨这两个平台在技术实现和开发生态上的关键差异,并分享一些实用的开发技巧,旨在为跨平台开发者提供有价值的见解和建议。
|
8天前
|
前端开发 编译器 iOS开发
探索iOS开发的未来:SwiftUI和Combine的革新之路
随着苹果不断推动其操作系统的进化,iOS开发领域正经历着一场前所未有的变革。本文将深入分析SwiftUI和Combine框架如何重塑iOS应用的开发流程,通过对比传统MVC模式与现代SwiftUI的差异,揭示Combine响应式编程范式在简化异步代码方面的巨大潜力。文章还将探讨这些技术如何影响开发者的生产力、应用的性能以及最终用户的体验。通过案例分析和数据支持,我们将展望iOS开发的新趋势,并讨论如何在不断变化的技术环境中保持竞争力。
|
18天前
|
编解码 Android开发 iOS开发
深入探索Android与iOS开发的差异与挑战
【6月更文挑战第24天】在移动应用开发的广阔舞台上,Android和iOS两大操作系统扮演着主角。它们各自拥有独特的开发环境、工具集、用户基础及市场策略。本文将深度剖析这两个平台的开发差异,并探讨开发者面临的挑战,旨在为即将踏入或已在移动开发领域奋斗的开发者提供一份实用指南。
39 13
|
14天前
|
iOS开发 开发者 UED
探索iOS开发中的SwiftUI框架
【6月更文挑战第28天】在移动应用开发的海洋中,SwiftUI作为iOS平台的新星,以其声明式语法和灵活性,正引领着界面设计的未来。本文将带你深入理解SwiftUI的核心概念、布局能力以及如何通过它提升开发效率,为开发者们提供一份实操指南,解锁SwiftUI的强大潜力。
187 1
|
21天前
|
iOS开发 开发者 容器
探索iOS开发中的SwiftUI框架
【6月更文挑战第21天】本文深入探讨了苹果在iOS开发中推出的SwiftUI框架,旨在为开发者提供一种声明式、更简洁的界面设计方法。文章首先概述了SwiftUI的核心概念和优势,接着通过一个天气预报应用实例,详细讲解了如何使用SwiftUI进行布局和用户界面的设计。此外,还讨论了SwiftUI与UIKit的差异,以及如何将SwiftUI集成到现有的项目中。最后,文章展望了SwiftUI的未来发展方向,包括潜在的改进和新特性。