天天看點

Autolayout 基礎 - MasonryAutolayout 基礎

<code>Archives</code> <code>iOS</code>

這兩天自學的時候,複習了下 autolayout。本來想來寫一篇文章記錄下學習内容,搜了一下寫的人真不少,也寫得挺不錯的。照理我就不用寫了,但心裡總有那麼一點點遺憾,這麼流行的東西,我部落格裡怎麼能沒有呢?既然如此,那就多寫點基礎内容。

<a target="_blank" href="#autolayout-%E5%9F%BA%E7%A1%80">Autolayout 基礎</a>

<a target="_blank" href="#interface-builder-%E4%BB%8B%E7%BB%8D">Interface Builder 介紹</a>

<a target="_blank" href="#align%E5%AF%B9%E9%BD%90">Align(對齊)</a>

<a target="_blank" href="#pin%E8%AE%BE%E7%BD%AE%E7%9B%B8%E5%AF%B9%E5%A4%A7%E5%B0%8F%E5%92%8C%E4%BD%8D%E7%BD%AE">Pin:設定相對大小和位置</a>

<a target="_blank" href="#resolve-auto-layout-issues%E8%A7%A3%E5%86%B3-autolayout-%E9%97%AE%E9%A2%98">Resolve Auto Layout Issues:解決 autolayout 問題</a>

<a target="_blank" href="#resizing-behavior">Resizing Behavior</a>

<a target="_blank" href="#sizeclass">SizeClass</a>

<a target="_blank" href="#%E9%87%8D%E5%86%99%E5%B8%83%E5%B1%80">重寫布局</a>

<a target="_blank" href="#%E4%BD%BF%E7%94%A8-xcode-6-%E9%A2%84%E8%A7%88">使用 Xcode 6 預覽</a>

<a target="_blank" href="#vflvisual-format-language">VFL(Visual Format Language)</a>

<a target="_blank" href="#autolayout-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98">Autolayout 常見問題</a>

<a target="_blank" href="#masonry%E6%9B%BF%E4%BB%A3-autolayout">Masonry:替代 Autolayout</a>

在 storyboard 界面的右下角,有這麼一排圖示

Autolayout 基礎 - MasonryAutolayout 基礎

滑鼠放上去停留一小段時間,就會告訴你它們的作用,從左至右依次是:

Align:用來設定對齊相關的限制;

Pin:設定相對大小和位置;

Resolve Auto Layout Issues:解決 autolayout 問題;

Resizing Behavior:設定重置大小會如何影響其他對象;

Autolayout 基礎 - MasonryAutolayout 基礎

下面這些是兩個視圖層次中同一級的 View 的對齊。

下面這些是 SuperView 和 SubView 的對齊,SuperView 是 SubView 的 Container

在對齊數值的白色輸入框内,點選右側下拉框可以選擇“Use Current Canvas Value”,意思是使用目前 Xib/Storyboard 内的內插補點。

最後一個 Update Frames 表示如何更新 frame,有三個選項,預設為 None 不更新

Autolayout 基礎 - MasonryAutolayout 基礎

最上面有四個矩形框和四條虛線,原來用過 auto resizing 的童鞋應該會比較眼熟。矩形框裡的數字表示目前的 View 到最近的 View (注意:不是 SuperView)邊緣的距離。

在矩形框下面有一行灰色字的可選項“Constrain to margins”,意思是在設定上述限制是相對于 margins 設定的,而 margin 預設距離是 16。如和上邊緣距離 306,加上 16,是以 View 的頂部和它上邊最近的 View 的距離是 312。

其他的選項

Autolayout 基礎 - MasonryAutolayout 基礎

可以選擇要處理的 Views:目前選中的 Views 或 Controller 内所有的 Views

Autolayout 基礎 - MasonryAutolayout 基礎

設定重置大小會如何影響其他對象,有兩個選項(預設已勾選)

(這個地方我也沒弄明白,我查了文檔和一些部落格,都隻是做了簡單文字說明,然後自己試了下勾選和未勾選的情況,還是找不到有什麼差別,是以也沒明白具體是如何影響。)

SizeClass 中文意思可以了解為尺寸等級,就是在 autolayout 的基礎上,加上螢幕尺寸類型的定義。SizeClass 的寬高有三種類型:Compact(緊湊)、Any(任意)、Regular(普通)

不同裝置螢幕的寬高類型

Autolayout 基礎 - MasonryAutolayout 基礎

當你具體選擇尺寸時, IB 會顯示出目前選擇的螢幕尺寸的相關資訊,如寬高類型,螢幕尺寸類型,這個尺寸适用于哪些裝置等。

如果你設定的某種類型螢幕的限制布局,在其他類型螢幕下出現不符合意圖的布局時,可以重寫布局,即重新設定該螢幕類型下的布局。

如圖的 UIView 設定了 wAny|hAny 上下左右四個限制

Autolayout 基礎 - MasonryAutolayout 基礎

點選這個 UIView,檢視 Attribute Inspector 有個 install 選項被勾選上了。

Autolayout 基礎 - MasonryAutolayout 基礎

Installed/UnInstalled 表示的意思是目前布局是否被安裝在什麼類型的螢幕上。Installed/UnInstalled 前面如果沒有東西,表示布局是安裝在 wAny|hAny 類型的螢幕上。現在如果我們要單獨設定某種類型螢幕的布局可以點選加号,選擇螢幕類型

Autolayout 基礎 - MasonryAutolayout 基礎

将新的螢幕類型的勾選取消掉,則目前布局在該類型下不起作用,此時就可以切換類型,重新設定所有限制。

若隻想修改一條限制,也可以點選 Size Inspector

Autolayout 基礎 - MasonryAutolayout 基礎

選擇 Constraints —— All 顯示所有限制,輕按兩下任意一條限制,會出現一個和之前類似的界面

Autolayout 基礎 - MasonryAutolayout 基礎

Installed 前面也有個加号,估計你也該猜到了,這裡的修改和之前也是類似的。

如果 Xcode 的 Inspector 一些選項前面有加号,就表明它可以被重寫,比如剛剛這幅圖中,Installed

在螢幕類型多了這麼多之後,做不同類型的螢幕适配也是需要花不少功夫。如果每次适配一種類型螢幕後,都要運作後才能檢視效果,效率簡直太低下了。Xcode 6 提供了 preview 預覽功能,針對這個問題可以節省不少時間。

點選 Xcode Tool Bar 的 Assistant Editor 按鈕,顯示另一個視窗

Autolayout 基礎 - MasonryAutolayout 基礎

選擇 Preview 展示預覽界面

Autolayout 基礎 - MasonryAutolayout 基礎

如果想在預覽中同時顯示不同類型的螢幕,可以在預覽界面的左下角點選加号,選擇更多裝置

Autolayout 基礎 - MasonryAutolayout 基礎

如果想要檢視橫屏/豎屏,點選裝置下方的旋轉按鈕即可

Autolayout 基礎 - MasonryAutolayout 基礎

設定了 autolayout 之後,在代碼中還能用 self.someView.frame 修改 frame 嗎?

不能

為什麼有些控件隻設定 x、y 值限制,也不會出錯?

UIKit 的一些控件如 UILabel、UIImageView 等有自适應特性,會根據内容自适應尺寸,是以不需要再限制其寬高。

同樣的限制用在 UIScrollView 和 UIImageViwe 上,為什麼會出現錯誤?

Masonry 是目前為止公認的 autolayout 最好的替代方案,文法簡潔、直覺,不會出現各種意外之外的布局。根據網上了解到的一些情況,Masonry 在大型項目中的效果比 autolayout 好很多。

舉個簡單的例子:要使一個 subview 填充 superview,但和 superview 的邊界間距(inset) 10 個像素。使用 NSLayoutConstraints 是這麼寫的

<code>UIView *superview = self;</code>

<code></code>

<code>UIView *view1 = [[UIView alloc] init];</code>

<code>view1.translatesAutoresizingMaskIntoConstraints = NO;</code>

<code>view1.backgroundColor = [UIColor greenColor];</code>

<code>[superview addSubview:view1];</code>

<code>UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);</code>

<code>[superview addConstraints:@[</code>

<code>//view1 constraints</code>

<code>[NSLayoutConstraint constraintWithItem:view1</code>

<code>attribute:NSLayoutAttributeTop</code>

<code>relatedBy:NSLayoutRelationEqual</code>

<code>toItem:superview</code>

<code>multiplier:1.0</code>

<code>constant:padding.top],</code>

<code>attribute:NSLayoutAttributeLeft</code>

<code>constant:padding.left],</code>

<code>attribute:NSLayoutAttributeBottom</code>

<code>constant:-padding.bottom],</code>

<code>attribute:NSLayoutAttributeRight</code>

<code>multiplier:1</code>

<code>constant:-padding.right],</code>

<code>]];</code>

一個簡單的布局竟然寫了這麼多代碼,有種要死的感覺。用 Masonry 又是什麼樣子呢?

<code>[view1 mas_makeConstraints:^(MASConstraintMaker *make) {</code>

<code>make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler</code>

<code>make.left.equalTo(superview.mas_left).with.offset(padding.left);</code>

<code>make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);</code>

<code>make.right.equalTo(superview.mas_right).with.offset(-padding.right);</code>

<code>}];</code>

代碼少了至少一半以上,終于能緩過氣來了。但是還不夠,還能更少。

<code>make.edges.equalTo(superview).with.insets(padding);</code>

至尊寶:整個世界都清淨了!!!

<a target="_blank" href="https://github.com/Masonry/Masonry">Masonry 的 Github 位址</a>

繼續閱讀