iOS自動布局進階用法及純手碼約束寫法

來源:互聯網
上載者:User

標籤:

本文主要介紹幾個我遇到的總結的進階用法(當然我相信肯定有不少比這還進階的)。 簡單的storyboard中上下左右約束,固定寬高啥的用法在這裡就不做贅述了。

autolayout自動布局是iOS6以後出現的,但是在開始的一段時間裡大家並不怎麼會用,都是一上來先勾掉。之後隨著5s,iPhone6的出現螢幕多種多樣。用多層if來判斷尺寸已經完全hold不住了才開始學習自動布局。

在這之前有個叫自動調整的autoresizing屬性,這個主要用於一個控制項和自己父控制項之間的關係。只有autolayout才真正可以在任意兩個控制項中建立關係。

 

關於autoresizing

autoresizing需要注意的是 storyboard中設定的約束和手碼中設定的約束是相反的。 storyboard圖形頁面裡點的右邊的線和下邊的線的意思是“固定”

而手碼中常用的autoresizingMasks屬性中的枚舉都是Flexible可“伸縮”的。 所以假如想要讓右邊和下邊的距離固定,在代碼中應該設定左邊和上邊的可伸縮約束。

1 yellowView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleTopMargin;

有了autolayout之後這個自動調整很少用了 一共七個屬性。

無,寬可伸縮,高可伸縮,左間距可伸縮,右間距可伸縮,上間距可伸縮,下間距可伸縮

     UIViewAutoresizingNone                 = 0,

     UIViewAutoresizingFlexibleWidth        = 1 << 1,

     UIViewAutoresizingFlexibleHeight       = 1 << 4,

     UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,

     UIViewAutoresizingFlexibleRightMargin  = 1 << 2,

     UIViewAutoresizingFlexibleTopMargin    = 1 << 3,

     UIViewAutoresizingFlexibleBottomMargin = 1 << 5

 每個枚舉值都是位移枚舉,可以在一行代碼中傳多個值。

 

關於label的自動識別大小

label想要在介面中顯示成這樣

意義是下面的控制項可以根據上面label的底部進行自動調整。 

這個不是用sizetofit設定的,而是用約束,會在程式運行中資料變了約束立即改變,尺寸也立即改變。

這種設計方法是:

1.設定label的左邊和上邊的約束,然後再設定下最寬度約束假設是150,把label裡面的lines屬性設定成0即隨意任意多行。 這樣裡面的文字就會自動換行並且一直顯示完,label的背景色也是自動匹配。

2.但是右邊還多出了一塊。label的右邊還有一塊藍色並不是緊緊的挨著。這時就要選中那個寬度的約束 再到右邊把Relation由原本的equal改成 less than or Equal 。這時候左邊的約束顯示變了  變成≤了。

運行之後結果是:這裡可以清楚的看到label的右邊緊緊挨著邊了。

3.但是有時候資料可能為空白,一旦為空白label的大小就被擠沒有了,下面的控制項也淩亂了。所以為了保證就算資料沒有空當也要留著佔位,就找給他設定兩個高度約束,一個是大於等於一個是小於等於,包裹成一個範圍。 這時候要把上面width的小於等於改成equal。

就像這樣 這時候運行效果 遇到大量文字和沒文字的兩種效果是

起到了佔位的作用。即使文字沒有地方還在。

 

關於Constraints在哪找的問題

左邊的圖constraints有的在label節點下有的在View節點下,究竟是什麼原因決定了constraints在哪個節點下面?

是看這個約束是否依賴了別的控制項,如果就是自己設定固定寬高啥的不關係到別人那就是在自己下面。如果依賴誰設定了間距,那這個約束就會放在自己和依賴的控制項的最小公用父控制項下。

   

 

 

關於手碼編寫autolayout約束

storyboard介面裡面的托拉拽固然方便但是不能大量操作(董鉑然原創),假如有類似的30個小控制項,storyboard就太麻煩了,手碼的話一個迴圈就完事了

手碼建立就是所謂的那七個參數的長的像句子似得方法

之後再在相應的節點下添加約束,有添加一個和添加一組 兩種方法。

// 高度約束(添加到yellowView身上)    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:50];    [yellowView addConstraint:heightConstraint];        // 間距約束(添加到self.view身上)    CGFloat margin = 20;    [self.view addConstraints:@[                                // 左邊                                [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:margin],                                                                // 右邊                                [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant: - margin],                                                                // 底部                                [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant: - margin]                                ]];}

這裡用到了一個核心公式

obj1.property1 =(obj2.property2 * multiplier)+ constant value

multiplier和constant 就是向量係數和位移量

還有為了避免和系統產生的自動調整的約束不衝突 一般加上這句

 系統預設這個屬性是yes

 

 

關於VFL語言 Visual Format Language,翻譯過來是“可視化格式語言”  是蘋果公司為了簡化Autolayout的編碼而推出的抽象語言相當於打出表意字元似得,而且要全在字串裡寫,遇到錯誤比較難調,但是相對來說代碼精簡了不少。然後在添加約束的時候就會用到系統提供的另外一種方法。
    NSArray *contraints = [NSLayoutConstraint constraintsWithVisualFormat:vfl options:kNilOptions metrics:metrics views:views];

VFL的詳細文法 可以在官方文檔中 搜 “Visual Format” 就能搜到 

上面的方法中傳到的兩個參數metrics 和 views 是兩個字典。(董鉑然原創) 第一個字典metrics是用來告訴系統裡面的每一個值對應哪個字母 

第二個字典views是 用來告訴裡面的每一個控制項對應字串裡的什麼

如果整個VFL語言裡的所有控制項你都是用原名寫在裡面的,那可以用宏代替

括弧裡可以傳多個值逗號隔開

 

關於常用的手碼約束的第三方架構

有 Masonry 和 UIView+Autolayout

架構地址是:

https://github.com/Masonry/Masonry 

https://github.com/smileyborg/UIView-AutoLayout

 

UIView+Autolayout架構

這個相對於masonry,是個輕量級的架構易於上手,裡面一共也就兩個檔案。也非常好用,都是用auto開頭。適用於約束不經常改變的項目

案例用法:

直接設定四周的間隔距離

[self.yellowView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(20, 20, 20, 20)]; //直接設定四周的間隔距離

設定三個間隔,然後再添加個高度,

[self.yellowView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(20, 20, 20, 20)excludingEdge:ALEdgeTop]; // 讓頂部約束無效    [self.yellowView autoSetDimension:ALDimensionHeight toSize:100]; // 自己再添加個高度約束正好四個

也可以直接設定大小

[self.yellowView autoSetDimensionsToSize:CGSizeMake(200, 200)];

總之還有很多用法,在這不一一介紹了,大概就是這個代碼風格。有興趣的可以去上面說的那個github地址上仔細查看。

 

 

Masonry架構這個架構是重量級的裡面好多檔案,難於上手,但是用熟練了的話比上面那個牛X,適合於約束要經常改變的項目。範例程式碼:添加距離四個方向20的間隔約束
[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {        // make代表yellowView        // 添加約束        make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(20, 20, 20, 20));    }];

下面這個是更新約束,非常方便會自動識別上左下右的屬性來更改。

[self.yellowView mas_updateConstraints:^(MASConstraintMaker *make) {        make.left.equalTo(self.view.mas_left).offset(100);        make.top.equalTo(self.view.mas_top).offset(100);        make.right.equalTo(self.view.mas_right).offset(-100);        make.bottom.equalTo(self.view.mas_bottom).offset(-100);    }];

還有一些別的屬性用法。

主要是作者設定的屬性比較多這張圖摘自他的github,有興趣可以去github仔細看

 關於想給約束改變添加動畫。因為約束的改變是瞬時操作的事情和frame的概念不一樣,所以把約束的代碼放在動畫的block裡是無效的正確做法是,把約束寫在上面,然後在動畫的block中包裹 layoutifneed 對了還有一個注意點是:需要依賴父控制項的約束要在添加了父控制項之後再寫。有什麼不同的看法歡迎評論。本部落格所有文章均原創,轉載請註明出處

iOS自動布局進階用法及純手碼約束寫法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.