天天看点

iOS屏幕适配-iOS笔记

1.【了解】屏幕适配的发展史

2.【了解】autoResizing基本用法

3.【掌握】autoLayout 的基本用法

4.【掌握】autoLayout代码实现

5.【理解】sizeClass的基本用法

随着iOS屏幕尺寸越来越多样化,屏幕适配也就越来越重要了。

iphone1 - iphone3gs时代,window的size固定为(320,480)。我们只需要简单计算一下相对位置就好了,不需要做屏幕适配。

iphone4 -

iphone4s时代,苹果推出了retina屏,但是给了码农们非常大的福利:window的size不变,所以也不需要做适配。

iphone5 - iphone5s时代,window的size变了(320,568)。这时AutoresizingMask派上了用场(为什么不用Autolayout?

因为还要支持ios5)。

iphone6+时代,window的width也发生了变化(相对5和5s的屏幕比例没有变化)。终于是时候抛弃AutoresizingMask改用Autolayout,因为不用支持ios5了,并且相对于屏幕适配的多样性来说autoresizingMask也已经过时了。

虽然autoresizing已经过时,但我们还是有必要了解一下的。autoResizing是苹果早期的屏幕适配的解决办法,iOS6之前完全可以胜任,因为苹果手机只有3.5寸的屏幕,在加上手机app很少支持横屏,所以iOS开发者基本不用怎么适配布局,所有的UI控件只要相对父控件布局就可以了,没错autoResizing就是一个相对于父控件的布局解决方法。autoResizing是UIView的属性,使用非常简单,但是功能远远没有autolayout那样强大。如果你的界面比较简单,要求的细节没有那么高,你也可以使用autoResizing去进行自动布局。特别注意autoResizing只能适用于控件和他父控件直接的关系,不能控制两个同层级的控件直接的关系。

在使用autoResizing进行屏幕适配,可以通过Xcode可视化的界面调整或者代码去适配。在通过Xcode可视化界面调整去适配之前,需要先去掉下图中的两个勾选(autoLayout、sizeClass)。

iOS屏幕适配-iOS笔记

可以通过下图看到autoResizing通过可视化能调整的只有6根线刚好和它的6个枚举值对应。

iOS屏幕适配-iOS笔记

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {

    UIViewAutoresizingNone

    = 0, 

UIViewAutoresizingFlexibleLeftMargin   = 1

<< 0,

UIViewAutoresizingFlexibleWidth  

     = 1

<< 1,

UIViewAutoresizingFlexibleRightMargin  = 1

<< 2,

UIViewAutoresizingFlexibleTopMargin  

 = 1 << 3,

UIViewAutoresizingFlexibleHeight  

    = 1 << 4,

UIViewAutoresizingFlexibleBottomMargin = 1 << 5

};

外边的4根虚线用来设置当前view距离父控件的上、下、左、右的距离是否固定不变的。

内部的2根带箭头的线来设置view是否跟随父控件来自适应width和height。

代码则可以通过(view.autoresizingMask = 枚举值)来设定autoResizing值。

autoResizing的功能仅此而已,如果我们要限制两个子控件之间的关系,他就无能为力了。这样显然不够用!!!

做苹果开发的一个好处是有一个很好的东家(Apple公司),他不仅很注重用户体验,而且还不忘为开发者去除一些不必要的麻烦(例如:ARC的出现...)。

autoLayout:可以在任意两个控件之间建立布局关系,可以是父子view也可以是兄弟view等。功能强大了许多,当然学习成本也高了不少。

autoLayout的基础理论:

1.view具有自我计算尺寸,布局的能力。通过它自身的内容,能够得到尺寸。

2.view的布局位置,确定于它与superview及其他view之间的关系。

3.与传统的autoresizingmask自适应相比,autoLayout更精确,能绝对的确定view的布局。

4.view不一定需要一个初始的Rect。autoLayout中,view如果有足够的约束(constraint),便可以确定自己的尺寸和位置,并且知道自己和其他view的关系。也就是想确定view的布局,就给它(们)添加约束(constraint)。

在storyboard中使用autoLayout进行屏幕适配一定要勾选Use

Auto Layout,和上面所演示的autoResizing相反。

iOS屏幕适配-iOS笔记

下面用一个案例来介绍在storyboard中使用autoLayout屏幕适配的基本操作。

我们需要适配两个等宽、等高的view之间的距离永远固定。autoResizing只能适用于控件和他父控件之间的关系,不能适用于同等级的两个控件之间的关系,所以我们必须使用autoLayout来实现。

勾选Use

Auto

Layout后,在storyboard布局区域底部有三个按钮,左数第一个是设置对齐方式相关的约束,具体如下图:

iOS屏幕适配-iOS笔记

左数第二个按钮是设置四个方向的约束和宽、高约束的,下图中有一个Constrain

to

margins选项,是如果我们的参考是父view的时候会屏幕边缘会有一个margin的宽度,不勾选者相当于屏幕边缘约束。

这里我让蓝色View的左、右距离父View边缘固定,并且高固定。这样得到蓝色View的(宽、x坐标、高)。还差一个y坐标,如果约束不齐全,请注意不要勾选下图绿色圈中的更新选项,保持None默认。

iOS屏幕适配-iOS笔记

当我点击Add

3 Constraints后,如下图所示,有红色箭头提示,标明目前控件的约束不全。并以虚线显示出目前约束会让View将改变的位置。

iOS屏幕适配-iOS笔记

选中要添加约束的控件,按住control键拖到参考控件也可以添加约束。这里我让蓝色View相当于父View垂直居中,这样y坐标也确认了,控件上的约束线都变成了蓝色,表示约束齐全并且都已经更新。如下图所示:

iOS屏幕适配-iOS笔记

然后让紫色View和蓝色View左对齐、右对齐、等高,并让紫色View相当于父控件垂直居中。

iOS屏幕适配-iOS笔记

修改两个View相当于父控件垂直居中对齐的偏移量一致,这样他们相对于父控件垂直居中的水平线(我也不知道咋形容,看下下图吧)距离相等。

iOS屏幕适配-iOS笔记

下图就是说明垂直居中的偏移量的,水平居中也是同理。

iOS屏幕适配-iOS笔记

添加约束后完成的效果图,如下所示:

iOS屏幕适配-iOS笔记

struct CGRect {

    CGPoint origin;

    CGSize size;

而AutoLayout是通过约束来实现布局的。一个view一旦使用了AutoLayout约束,那么它的frame将永远都是0,所以在使用AutoLayout之前需要两个准备工作。

1.禁用autoResizing,因为autoresizing和autoLayout是不能共存的

设置translatesAutoresizingMaskIntoConstraints为NO。

2.创建约束对象并添加约束

1.如果参考是本身才添加到本身。

2.如果参考是父控件就添加到父控件。

3.如果参考是其他控件则添加到共同的父控件。

我们通过一个案例来演示代码实现autoLayout,我们的需求是实现两个View永远等高,永远右对齐,但其中一个View的宽度是另一个View宽度的一半。需求实现后的效果如下图所示:

iOS屏幕适配-iOS笔记

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    //创建蓝色View并添加到父视图

    UIView *blueView = [[UIView

alloc] init];

    blueView.backgroundColor =

[UIColor blueColor];

    [self.view

addSubview:blueView];

    //创建红色View并添加到父视图

    UIView *redView = [[UIView

    redView.backgroundColor =

[UIColor redColor];

addSubview:redView];

    //禁用autoresizing

blueView.translatesAutoresizingMaskIntoConstraints = NO;

redView.translatesAutoresizingMaskIntoConstraints = NO;

    //创建蓝色View的约束

    NSLayoutConstraint *blueTop =

[NSLayoutConstraint constraintWithItem:blueView

attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual

toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0

constant:30];

    NSLayoutConstraint *blueLeft

= [NSLayoutConstraint constraintWithItem:blueView

attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual

toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0

    NSLayoutConstraint *blueRight

attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual

toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0

constant:-30];

    NSLayoutConstraint

*blueHeight = [NSLayoutConstraint constraintWithItem:blueView

attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual

toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0

constant:50];

    //添加蓝色View的约束

addConstraints:@[blueTop,blueLeft,blueRight]];

    [blueView

addConstraint:blueHeight];

    //创建红色View的约束

    NSLayoutConstraint *redTop =

[NSLayoutConstraint constraintWithItem:redView

toItem:blueView attribute:NSLayoutAttributeBottom multiplier:1.0

    NSLayoutConstraint *redRight

= [NSLayoutConstraint constraintWithItem:redView

    NSLayoutConstraint *redLeft =

toItem:blueView attribute:NSLayoutAttributeCenterX multiplier:1.0

constant:0];

    NSLayoutConstraint *redHeight

    //添加红色View的约束

addConstraints:@[redTop,redRight,redLeft]];

    [redView

addConstraint:redHeight];

}

与其说科技的发展,拉近了空间中任意两点的距离,让交流、信息传递更加便捷。倒不如说由于交流和信息传递的需求更加迫切而推动了科技的进步。大屏显然是一典型的例子,屏幕尺寸的相对增大,一定程度上方便了交流和信息传递,反之,相对小的屏幕对信息传递会有一定的局限。所以苹果推出大屏幕的手机也是人

类进步的需要,并不是什么跟风,扯淡结束。

屏幕大了,尺寸多了,带给开发者的自然是适配方面的工作量和思考。正如大家知道的那样,苹果是一家最具追求的公司,他当然会推出可行的解决方案就是sizeClass。

sizeClass:对屏幕尺寸进行了抽象,不在拘泥于具体尺寸。因为尺寸一直都在变化,我们如果按照尺寸去做适配,一定会很累的。

sizeClass针对iOS设备的屏幕进行了抽象分类:

compact (紧凑 - 小)、Any (任意)、Regular (宽松 - 大)。

总结几点:

1.sizeClass只是对屏幕进行了抽象分类,具体做屏幕的适配还得用autoLayout。

2.没有了横竖屏的概念,也没有了具体尺寸,不用在去谈具体的iphone6 plus还是ipad air2。

3.把高度和宽度都抽象为上边的3种,3*3也就是总共9种类型。注意是9种类型,不是9种屏幕尺寸。

这样做的结果就是你可以做好一个interface

builder适配,然后不管在iphone还是ipad中都可以用了,这就是苹果的意愿。打开xcode如果新建一个universal项目,在xcode6之前会默认有两个storyboard,一个是iphone的,一个是ipad版本的。xcode6之后只有一个,并且是正方形的,也就是说不管你做那种屏幕尺寸的app(无论是ipad还是iphone),都只用这一个storyboard就可以了。

具体分类如下:

iOS屏幕适配-iOS笔记

图中9个格子代表 3*3的9中抽象,具体每种代表了那些含义可以选中看看。

比如iphone的竖屏它是这样抽象的:compact width

* regular height。

iOS屏幕适配-iOS笔记

然后适配还是使用autoLayout,我就不再重复演示了,需要注意的是我们需要根据需求选择正确的sizeClass抽象屏。

iOS8加了sizeclass后,控件也多了个属性,在storyboard上托个label出来(以label为例),选中,在右边的菜单区域可以看

到:installed。这个是用来控制改控件什么情况下显示,当前什么都没约束,表示Any *

Any,就是不管是iphone什么尺寸还是ipad什么尺寸都可以显示,点击左边的小加号<code>+</code>可以用sizeClass控制什么情况显示。同样的还有字体、图片显示。

iOS屏幕适配-iOS笔记

控制什么情况显示什么样的字体。

iOS屏幕适配-iOS笔记

各种苹果设备的分辨率

iOS屏幕适配-iOS笔记

各种iPhone对应尺寸

iOS屏幕适配-iOS笔记

温馨提示:欢迎分享此文,分享转载请注明出处!

继续阅读