【UI】AutoLayout

目錄
一、屏幕適配
二、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 WidthEqual 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);
    }];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容