说明:本文是我在原文的基础上做的整理,如有异议请参考原文。
原文地址:http://www.cocoachina.com/industry/20140411/8143.html?utm_source=tuicool&utm_medium=referral
一、评估新的设计思想(我理解为ios7视图坐标上移的原因)
苹果希望iOS 7改进的一个关键点就是“依从”,my Mac给它的定义是“依从和尊重”。我们的界面应该依从内容,这正是app的核心体验。苹果的《
人机界面指南》指出“用户界面帮助用户理解并与内容交互,但从不与内容竞争”。
例如“Safari”:
当你第一次访问网站是,你可以任意使用所有的控件。URL栏和刷新按钮在顶部,底部的工具栏包含其他需要可与app交互的按钮。当你开始滚动页面时,UI将内容呈现在屏幕上。顶部的导航栏收缩只显示基本的URL,底部的工具栏完全隐藏了。如果用户需要用这些按钮,只需要点击上部的导航栏或者向后滚动。
为了遵循iOS 7的依从要求,一些类也发生了改变。下面我们来看下UINavigationController,而同样的规则也应用于UITabBarController中。
iOS 6及之前的版本中,导航控制器的内容视图
仅仅
是从UINavigationBar的下面
扩展到
屏幕底部。然而,iOS 7中内容视图
从屏幕的最顶部
扩展到最底部,从导航栏下面显示。
看看下面的iOS 6和iOS 7中地图的屏幕截屏。注意到,在iOS 7中你可以很容易看到导航栏(以及底部的工具栏)下面的模糊内容。
内容是王道,半透明的UI元素暗示了其后边的内容。
针对ios7新的设计思想,我们在界面布局时有如下三种设计方案,使其看起来在iOS7和iOS6中都适合:
1.如果你的界面
没有使用
滚动视图,那可以使用Auto Layout向上或向下移动内容以同时支持iOS 6和iOS 7。也可以设置
edgesForExtendedLayout
属性禁止界面坐标上移。
2.如果你
使用
滚动视图,充分利用UIViewController‘s 和automaticallyAdjustsScrollViewInsets的特性来解决你的困难。如果出于某种原因,你没能利用这个属性,那
么你需要调整滚动视图的contentInset和scrollIndicatorInsets属性来达到相似的结果。
3.如果你使用storyboards,将视图固定到“Top Layout Guide”。
二、例子1--界面没有使用滚动视图
如果你没有用滚动视图,那么是调整界面同时适应iOS6和iOS7是非常简单的。
1.使用自动布局;
2.在UI顶部使用约束来固定一个视图,其他的视图直接或者间接地固定在这个视图上;
3.在NSLayoutConstraint上创建一个IBOutlet;
4.基于应用程序运行的OS版本,有条件的在viewDidLoad上修改这个约束。
接下来让我们逐一看这些步骤:
通常,你将在界面的顶端有一个子视图。我通常把这种视图称为anchor view。这个子视图会通过一个top constraint居于父视图的顶端,其余子视图将会以某种方式相对于top view。
看看下面的屏幕截图(设计时考虑到iOS 7,与之前的屏幕截图不同)
在iOS 6中,在name标签上部将会有很多的空白区域。这是因为相对于屏幕的顶端,视图的顶部是在导航栏的底部,正如你在上面Interface Builder中看到的屏幕截图一样。
为了消除这些空白
,我们只需要从顶部约束常量中减去状态栏和导航栏的高度即可。
为此,我们需要在代码中为约束创建一个outlet,以便我们能够在运行时进行调整。如下:
- @property (nonatomic, weak) IBOutlet NSLayoutConstraint *topConstraint; //确保将这个连接到XIB文件中的NSLayoutConstraint(如果你用编程方式做,那么你已经有了一个引用约束。)
最后你需要做的事情就是
根据OS版本
来更新约束常量。如果你使用的是XIB(首次连接outlet),那么viewDidLoad非常适合;或者使用loadView,如果你以编程方式搭建界面。
在上面的代码中,使用视图控制器的topConstraint 属性来决定是运行在iOS 6上还是iOS 7上,只有iOS 7中有这个属性。这个属性与布局界面十分相关,你可以它作为一个参考点。如果视图控制器没有响应那个选择器,那么你是在iOS 6上运行,
因此你需要在顶部删除XIB中的空白区域
。为此,要去掉状态栏和导航栏的高度。(如果你在iOS 6上创建界面,并且需要运行在iOS 7上,那么你就要添加空白区域而不是删除它,因此需要“self.topConstraint.constant = self.topConstraint.constant + 64;”。这将解决文章开头所用截图中存在的问题。
三、例子2--界面使用了滚动视图
假定你的界面有滚动视图(或者其子类),出于一个或者其他多个原因,你的界面不能在iOS 6或者iOS 7上稳定运行,你该怎样修复这个问题呢?
1.如果你有在界面后边的单个滚动视图,可使用UIViewController的automaticallyAdjustsScrollViewInsets(我会解释这一点)
2.如果你有多个滚动视图,或者视图不在界面后边,那可以手动调整滚动视图的contentInset和scrollIndicatorInsets属性。
让我们来看看这两种情况。
在iOS 7中,UIViewControllers有一个属性automaticallyAdjustsScrollViewInsets,默认为YES。该属性会简单化你的工作,让你理解它是如何工作的。
如果你有一个滚动视图,
要么是视图控制器(比如UITableViewController)的根视图,要么是索引为0的子视图(前提条件)
,那么这个属性将调整contentInset和scrollIndicatorInsets。这将允许在导航栏下启动滚动视图内容和滚动指示器(如果你的视图控制器是一个导航控制器)。与在导航栏下面手动调整滚动视图的框架不同,
这个方法允许你的滚动视图内容在导航栏下面滚动,这iOS 7很重要的一个方面
。
如果你的滚动视图
不符合
之前的标准(或者你把automaticallyAdjustsScrollViewInsets设为NO),那么你需要手动更改这两个属性:
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
- if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
-
- UIEdgeInsets insets = UIEdgeInsetsMake(64, 0, 0, 0);
- self.tableView.contentInset = insets;
- self.tableView.scrollIndicatorInsets = insets;
- }
- }
如果滚动视图后面有一个背景图片,或者在一个视图控制器中有多个滚动视图,你可能会想这么做。由于iOS 6中没有这个属性,那你只能用现有的方法了。
四、例子3--界面使用Storyboards
苹果喜欢storyboards,他们能做出看上去很神奇的东西。所以你如何使用storyboards?
1.使用Auto Layout
2.如果不用滚动视图,那创建一个“Top Layout Guide”的顶级约束。
3.如果使用滚动视图,那么你可用上面的滚动视图步骤(并且你可以在视图控制器上的属性面板中设置automaticallyAdjustsScrollViewInsets 的属性)。
这很简单,让我们一下看看这两点。
创建一个“Top Layout Guide”的顶级约束很简单,如下屏幕截图所示:
只要一切都相对于“Top Layout Guide”进行了约束,那么你的界面在iOS 6和iOS 7中就会正确显示。
你可能会说,“等一下,Christian。你说过Top Layout Guide是只有iOS 7才有的特性。”你说的没错。苹果开发者就是在这里施展魔术的。在iOS 7中,苹果给topLayoutGuide正确地添加了约束,但是在iOS 6中,苹果用{0,0,0,0}框架创建了UIView,将顶级约束添加到这个视图上。我希望它像XIB文件一样正常运行,但很可惜。
对于滚动视图,参考上一小节中的建议。如果你需要设置automaticallyAdjustsScrollViewInsets属性,你可以在视图控制器上的属性面板中设置。