目錄
一、屏幕適配
二、AutoLayout
三、AutoLayout實(shí)現(xiàn)屏幕適配
?1、AutoLayout在可視化布局中實(shí)現(xiàn)屏幕適配
?2、AutoLayout在純代碼布局中實(shí)現(xiàn)屏幕適配
四、例子
一、屏幕適配
在用戶眼中,屏幕是由一個一個的像素(pixel、px)組成的,像素越高屏幕越清晰,這就是物理分辨率。在開發(fā)者眼中,屏幕是由一個一個的點(diǎn)(point、pt)組成的,點(diǎn)又由像素組成,這就是開發(fā)分辨率。
比如iPhone3GS的物理分辨率為320 x 480px,開發(fā)分辨率為320 x 480pt,這就代表iPhone3GS上面有320 x 480個點(diǎn),而每個點(diǎn)里都只有一個像素;iPhone4的物理分辨率為640 x 960px,開發(fā)分辨率為320 x 480pt,這就代表iPhone4上面有320 x 480個點(diǎn),但是每個點(diǎn)里有2 x 2 = 4個像素;iPhone5的物理分辨率為640 x 1136px,開發(fā)分辨率為320 x 568pt,這就代表iPhone5上面有320 x 568個點(diǎn),每個點(diǎn)里也有2 x 2 = 4個像素;iPhone6的物理分辨率為750 x 1334px,開發(fā)分辨率為375 x 667pt,這就代表iPhone6上面有375 x 667個點(diǎn),每個點(diǎn)里也有2 x 2 = 4個像素;iPhone6P的物理分辨率為1242 x 2208px,開發(fā)分辨率為414 x 736pt,這就代表iPhone6P上面有414 x 736個點(diǎn),每個點(diǎn)里有3 x 3 = 9個像素。
我們開發(fā)者面向的是開發(fā)分辨率,不用特別關(guān)心物理分辨率,正是因?yàn)椴煌臋C(jī)型有不同的開發(fā)分辨率,所以我們才得做屏幕適配——讓一個控件在不同的機(jī)型上有相同的相對位置和相對大小。
二、AutoLayout
AutoLayout是iOS6引入的一種專門用來做UI布局的“自動布局”技術(shù),使用它能夠很輕松地解決屏幕適配問題,從而大大提升開發(fā)效率。
AutoLayout的兩個核心概念:
- 約束:通過給控件添加約束,來決定控件的位置和尺寸
- 參照:添加約束時(shí),是參照誰來添加(可以是父控件或兄弟控件)
AutoLayout的核心計(jì)算公式:
某個控件的約束 = 參照控件的約束 * multiplier + constant
三、AutoLayout實(shí)現(xiàn)屏幕適配
1、AutoLayout在可視化布局中實(shí)現(xiàn)屏幕適配
- 設(shè)置位置和寬高面板

第一部分:用來設(shè)置一個控件跟距離它最近的控件(可以是父控件或兄弟控件)的上左下右間距,如果勾選了Constrain to margins,系統(tǒng)會默認(rèn)加個20pt的邊距,一般我們不勾選。此外我們還可以點(diǎn)擊約束右邊的小箭頭來設(shè)置約束到底參照誰。
第二部分:用來設(shè)置一個控件的寬高。
第三部分:Aspect Ratio用來設(shè)置一個控件的寬高比;Equal Width和Equal Height用來設(shè)置多個控件等寬等高。
- 設(shè)置對齊方式面板

第一部分:用來設(shè)置多個控件上對齊、左對齊、下對齊、右對齊。
第二部分:用來設(shè)置多個控件橫向?qū)R和豎向?qū)R。
第三部分:用來設(shè)置一個控件相對于它的父控件橫向?qū)R和豎向?qū)R。
- 約束處理面板

第一部分:用來更新和刪除選中控件的約束。(更新約束的快捷鍵是cmd Option =)
第二部分:用來更新和刪除所有控件的約束。
- 修改約束
當(dāng)我們想要修改約束時(shí),可以選中控件,找到相應(yīng)的約束修改掉。(當(dāng)然我們也可以修改約束的優(yōu)先級,一個控件上如果添加了兩個同樣作用的約束,那么這兩個約束就會產(chǎn)生沖突,我們就得給它們設(shè)置優(yōu)先級,這樣就可以消滅掉沖突了,優(yōu)先級較高的約束會先起作用,優(yōu)先級較低的約束會先不起作用,等優(yōu)先級較高的約束被刪除后優(yōu)先級較低的約束才會起作用)

2、AutoLayout在純代碼布局中實(shí)現(xiàn)屏幕適配
AutoLayout在純代碼布局中的實(shí)現(xiàn)我們一般都會使用一個三方庫——Masonry,使用它我們可以非常簡單地完成純代碼AutoLayout,而不用寫蘋果官方提供的非常惡心的NSLayoutConstraint或VFL代碼。
1注意使用Masonry給控件添加約束之前,必須先把控件添加到父控件上,和可視化添加約束一樣,一個控件需要4個約束
2Masonry常用的三個方法
- mas_makeConstraints:用來新增約束
- mas_updateConstraints:用來更新約束(例如做動畫),不是用來新增約束
- mas_remakeConstraints:也是用來更新約束,不過mas_remakeConstraints會清除控件之前所有的約束,然后再添加新的約束,而mas_updateConstraints只是更新控件的某個約束而已
3Masonry常用的一些屬性
- top、bottom、left、right --> edges(通常與insets連用)
- width、height --> size
- centerX、centerY --> center
4Masonry常用的鏈?zhǔn)秸Z法(里面不能有純數(shù)字的加減乘除)
- equalTo():表示兩個控件的某個屬性相等,用于上下左右、寬高、中心X中心Y這種簡單屬性,如果屬性相同的話可以不寫,不同的話必須寫mas_屬性
- mas_equalTo():也表示兩個控件的某個屬性相等,用于edges、size、center這種結(jié)構(gòu)體屬性和具體數(shù)值
- multipliedBy():核心計(jì)算公式里的multiplier
- offset():核心計(jì)算公式里的constant
四、例子
- 指定高度、橫向指定間距、自適應(yīng)寬度、等間距等寬排列:從左往右趕,不給寬度


- 指定高度、橫向指定寬度、自適應(yīng)間距、等間距等寬排列:如果控件是奇數(shù)個,就先把中間的控件給布局好,因?yàn)樗腸enterX肯定跟父控件的centerX一樣,接下來就跟控件是偶數(shù)個一樣了;如果控件是偶數(shù)個,那么父控件的centerX左邊從左往右的第N個控件的centerX為:(2N - 1) / 控件個數(shù),父控件的centerX右邊從右往左的第N個控件的centerX為:2 - (2N - 1) / 控件個數(shù)


- UILabel自適應(yīng)寬度,只需要設(shè)置上左高度三個約束;UILabel自適應(yīng)高度,只需要設(shè)置上左寬度三個約束,并設(shè)置numberOfLines為0即可


- 聊天氣泡根據(jù)文本內(nèi)容自適應(yīng)高度和寬度:先做好label的自適應(yīng)高度和寬度,然后讓氣泡的底部和右側(cè)等于label的底部和右側(cè),就可以實(shí)現(xiàn)氣泡的自適應(yīng)高度和寬度了

UIView *bubbleView = [[UIView alloc] init];
bubbleView.backgroundColor = [UIColor redColor];
[self.view addSubview:bubbleView];
UIImageView *avatarImageView = [[UIImageView alloc] init];
avatarImageView.backgroundColor = [UIColor greenColor];
[bubbleView addSubview:avatarImageView];
UILabel *contentLabel = [[UILabel alloc] init];
contentLabel.backgroundColor = [UIColor blueColor];
contentLabel.text = @"哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈";
contentLabel.numberOfLines = 0;
[bubbleView addSubview:contentLabel];
[avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.equalTo(bubbleView).offset(10);
make.width.height.mas_equalTo(20);
}];
[contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
/*
約束1、2、3:可以保證contentLabel自適應(yīng)高度
約束1、2、4:可以保證contentLabel自適應(yīng)寬度
*/
// 約束1
make.top.equalTo(avatarImageView);
// 約束2
make.left.equalTo(avatarImageView.mas_right).offset(10);
// 約束3,注意不能寫死,否則就不能自適應(yīng)寬度了
make.width.mas_greaterThanOrEqualTo(20);
// 約束4,注意不能寫死,否則就不能自適應(yīng)高度了
make.height.mas_greaterThanOrEqualTo(20);
}];
[bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(20);
make.left.equalTo(self.view);
// 我們只需要讓氣泡的底部等于文本的底部,就可以實(shí)現(xiàn)氣泡的自適應(yīng)的高度了
make.bottom.equalTo(contentLabel).offset(10);
// 我們只需要讓氣泡的右側(cè)等于文本的右側(cè),就可以實(shí)現(xiàn)氣泡的自適應(yīng)的寬度了
make.right.equalTo(contentLabel).offset(10);
// 但是為了避免氣泡過寬超出屏幕,我們需要額外給氣泡加一個最寬的約束
make.right.mas_lessThanOrEqualTo(self.view);
}];