iPhone6分辨率与适配
(via:sunnyxx's blog)
分辨率和像素
经新xcode6模拟器验证(分辨率为pt,像素为真实pixel):
1.iPhone5分辨率320x568,像素640x1136,@2x
2.iPhone6分辨率375x667,像素750x1334,@2x
3.iPhone6 Plus分辨率414x736,像素1242x2208,@3x,(注意,在这个分辨率下渲染后,图像等比降低pixel分辨率至1080p(1080x1920)
自动适配
不处理时自动等比拉伸,如果在老工程打印屏幕frame,依然是320x568
对比自动适配的和完美适配的导航栏就能看出问题:
因为拉伸所以会有一些虚,导航栏明显比64要大,但相比3.5寸到4寸的留黑边还是好很多。
如何关闭自动适配方案呢?这个还是老思路,换启动图:
除了换启动图外,不得不说的是,新Xcode中可以使用一个xib来设置启动图:
不过这个xib不能关联任何的代码(不能自定义View的Class,不能IBOutlet,不能加Object),可以理解成这个xib就是一张截图,这个方案的好处在于可以使用到Size Classes来针对不同屏幕布局这个xib(感兴趣可以看《Size Classes初探》)
关于手动适配
只要手动指定了启动图或者那个xib,屏幕分辨率就已经变成应有的大小了,老代码中所有关于写死frame值的代码通通倒霉,如果去手动适配就要全部适配,建议在找到个可行方案前先不要做修改,自动适配方案还算不影响使用。
面对4个分辨率的iPhone,建议使用Auto Layout布局 + Image Assets管理各个分辨率的图片 + Interface Builder(xib+storyboard)构建UI,Size Classes在低版本iOS系统的表现未知。想要这套手动适配方案,起码你的工程需要部署在iOS6+,还不用AutoLayout布局的会死的蛮惨。
关于Xcode 6
模拟器路径被换成了 ~/Library/Developer/CoreSimulator/Devices/
xcode6中已经找不到iOS6的模拟器了,是时候说服大家放弃iOS7-了
现在起提交App Store强制需要支持64位,是时候梳理一遍所有依赖的第三方lib,更新到64位。(编辑注:这一条据说是个bug)
关于AutoLayout,最早从iOS6开始引入使用。
AutoLayout是什么?
使用一句Apple的官方定义的话 关键词:- 基于约束 -和以往定义frame的位置和尺寸不同,AutoLayout的位置确定是以所谓相对位置的约束来定义的,比如x坐标为superView的中心,y坐标为屏幕底部上方10像素等
- 描述性 - 约束的定义和各个view的关系使用接近自然语言或者可视化语言(稍后会提到)的方法来进行描述
- 布局系统 - 即字面意思,用来负责界面的各个元素的位置。
AutoLayout和Autoresizing Mask的区别
AutoresizingMask是我们的老朋友了…如果你以前一直是代码写UI的话,你肯定写过UIViewAutoresizingFlexib- AutoLayout可以指定任意两个view的相对位置,而不需要像AutoresizingMask那样需要两个view在直系的view hierarchy中。
- AutoLayout不必须指定相等关系的约束,它可以指定非相等约束(大于或者小于等);而AutoresizingMask所能做的布局只能是相等条件的。
- AutoLayout可以指定约束的优先级,计算frame时将优先按照满足优先级高的条件进行计算。
Autoresizing Mask是AutoLayout的子集,任何可以用AutoresizingMask完成的工作都可以用AutoLayout完成。AutoLayout还具备一些AutoresizingMask不具备的优良特性,以帮助我们更方便地构建界面。
AutoLayout基本使用方法
Interface Builder
手动使用API添加约束
创建
iOS6中新加入了一个类:NSLayoutConstraint,一个形如这样的约束- item1.attribute = multiplier ? item2.attribute + constant
1 | [NSLayoutConstraint constraintWithItem:button |
2 | attribute:NSLayoutAttributeBottom |
3 | relatedBy:NSLayoutRelationEqua |
4 | toItem:superview |
5 | attribute:NSLayoutAttributeBottom |
6 | multiplier:1.0 |
7 | constant:-padding] |
添加
在创建约束之后,需要将其添加到作用的view上。UIView(当然NSView也一样)加入了一个新的实例方法:- -(void)addConstraint:(NSLayoutConstraint *)constraint;
- 对于两个同层级view之间的约束关系,添加到他们的父view上
- 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
- 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
刷新
可以通过-setNeedsUpdateConstraintVisual Format Language 可视格式语言
UIKit团队这次相当有爱,估计他们自己也觉得新加约束的API名字太长了,因此他们发明了一种新的方式来描述约束条件,十分有趣。这种语言是对视觉描述的一种抽象,大概过程看起来是这样的:accept按钮在cancel按钮右侧默认间距处最后使用VFL(Visual Format Language)描述变成这样:
1 | [NSLayoutConstraintconstraintsWithVisualFor "[cancelButton]-[acceptButton]\" |
2 | options:0 |
3 | metrics:nil |
4 | views:viewsDictionary]; |
1 | UIButton *cancelButton = ... |
2 | UIButton *acceptButton = ... |
3 | viewsDictionary =NSDictionaryOfVariableBi |
{ acceptButton = ""; cancelButton = ""; }
当然,不嫌累的话自己手写也未尝不可。现在字典啊数组啊写法相对简化了很多了,因此也不复杂。关于Objective-C的新语法,可以参考我之前的一篇WWDC2012笔记:
WWDC 2012Session笔记——405 Modern Objective-C
。在view名字后面添加括号以及连接处的数字可以赋予表达式更多意义,以下进行一些举例:
- [cancelButton(72)]-12-[acceptButton(50)]
- 取消按钮宽72point,accept按钮宽50point,它们之间间距12point
- [wideView(>=60@700)]
- wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
- V:[redBox][yellowBox(==redBox)]
- 竖直布局,先是一个redBox,其下方紧接一个宽度等于redBox宽度的yellowBox
- H:|-[Find]-[FindNext]-[FindField(>=20)]-|
- 水平布局,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线'|‘表示superview的边缘)
容易出现的错误
因为涉及约束问题,因此约束模型下的所有可能出现的问题这里都会出现,具体来说包括两种:- Ambiguous Layout 布局不能确定
- Unsatisfiable Constraints 无法满足约束
- po [[UIWindow keyWindow] _autolayoutTrace]
- [view constraintsAffectingLayo
utForOrientation/Axis:NSLayoutConstraintOrient ationHorizontal/Vertical] - [view hasAmbiguousLayout]
- [view exerciseAmbiguityInLayou
t]
- [view exerciseAmbiguityInLayou
布局动画
动画是UI体验的重要部分,更改布局以后的动画也非常关键。说到动画,CoreAnimation又立功了..自从CA出现以后,所有的动画效果都非常cheap,在auto layout中情况也和collectionview里一样,很简单(可以参考 WWDC2012 Session笔记——219 Advanced Collection Views and Building CustomLayouts ),只需要把layoutIfNeeded放到animationblock中即可~ 1 | [UIView animateWithDuration:0.5 animations:^{ |
2 | [viewlayoutIfNeeded]; |
3 | }]; |