Masonry – AutoLayout的進化
在iOS的世界之中,如果要好好的把排版呈現出來,你必需要依靠auto layout的幫忙,auto layout定義了當物件container變大或變小時,物件的大小跟相對位置,有了auto layout的幫忙,才有辦法在4吋,5吋或之後出現的5.5吋手機上面正常呈現外觀而不會炸掉。
很不幸的是,在Objective C上面用code寫auto layout的規則,是一件很痛苦的事,請看以下的code:
[NSLayoutConstraint constraintWithItem:aView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top] [NSLayoutConstraint constraintWithItem:aView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeBottom multiplier:1.0 constant:padding.top] [NSLayoutConstraint constraintWithItem:aView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:padding.top] [NSLayoutConstraint constraintWithItem:aView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeRight multiplier:1.0 constant:padding.top]
這幾條規則只是要講一個簡單的概念,就是將 aView 這個東西的上下左右都延展到跟它的parent一樣大。NSLayoutConstraint雖然非常靈活,但寫起來非常冗長,而且這樣的code一點都不好讀。
不過拜科技之賜(?),現代iOS世界出現了一個這樣的framework,Masonry,完全可以解決iOS autolayout過於煩瑣的問題。讓我們直接來看一下語法,上面那樣的規則,如果用Masonry寫,會怎樣呢?
[aView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).with.insets(UIEdgeInsetsZero);
}];
上面這段code,語意上是:我要讓aView的邊界,都跟它的superview緊貼住。跟最上面用NSLayoutConstraint寫出來的外星語一模一樣,而且用Edge來描述,相對於用很多constant=0來說,語意上更加直觀了。更重要的是,這種寫法因為語意完整的關係,所以很好記,不像visual format那樣有點像多學一個語法,如果想要在程式裡撰寫auto layout,非常推薦使用這個Lib。
Swift的對應版是 SnapKit (Link),語法基本上是一樣的。
安裝
請愛用CocoaPods(“http://cocoapods.org/"):
pod 'Masonry'
基本語法
以上面的情境為例:
[aView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).with.insets(UIEdgeInsetsZero);
}];
這段code是要設定讓 aView 的大小跟superview一模一樣。
為了講解方便,我把它拆成更容易理解的語法:
[aView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superview.mas_top).with.offset(0);
make.left.equalTo(superview.mas_left).with.offset(0);
make.bottom.equalTo(superview.mas_bottom).with.offset(0);
make.right.equalTo(superview.mas_right).with.offset(0);
}];
這段code主軸就是mas_makeConstraints
這個method,這個method是說我想要開始在 aView 上面加auto layout的規則了。
在這個method裡面,主要的參數是一個block,帶有一個傳入值_make_,這個make你可以想像成就是 aView 的代表,在block裡面我們都使用_make_代替 aView 。接下來我們來看一下block裡面的第一行:
make.top.equalTo(superview.mas_top).with.offset(0);
這一行翻成白話文,指的就是我想要把 aView (make
)的頂端(top
)對齊(equalTo
)superview的頂端(mas_top
),並且設定中間沒有空隙(with.offset(0)
),這裡面有幾個關鍵字:
- top:代表actor(aView)的某個部份,可能的值有
- top
- bottom
- left
- right
- height
- width
…等等
- equalTo():代表aView跟其它view之間的關係,可能的值有:^1
- equalTo
- lessThanOrEqualTo
- greaterThanOrEqualTo
另外這個method裡面的參數就是要對齊的view跟該view的對齊基準點
- mas_top:這關鍵字代表的是某個view的頂端,可能的值還有:^2_
- mas_top_
- mas_bottom_
- mas_left_
- mas_right_
- mas_width_
- mas_height_
…等等
- offset():這個代表跟相對物件的關係值,以上面的code為例,就是兩個view之間的距離是0。
^1: Not all things are created equal(“https://github.com/Masonry/Masonry#not-all-things-are-created-equal")
^2: MASViewAttribute(“https://github.com/Masonry/Masonry#1-masviewattribute")
更多範例
上面示範了view對齊其它view的做法,那如果我想要指定特定view的寬度呢?
[aView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(@400);
}];
你可以直接這樣下,代表的就是我想要讓aView的寬度固定在400。要注意的是,equalTo如果是傳某個特定的值,那它一定要是NSNumber不能是primitive value。
設定優先權
如果你想要設定規則的優先權,可以在with這個關鍵字之後,下.priority()
,如下:
[aView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(@400).with.priority(1000);
}];
或者使用其它可能的關鍵字:^3
- .prority()
- .priorityHigh
- .priorityMedium
- .priorityLow
後面三個都是常數值,直接定義好讓你方便取用。
看完了這些簡單的應用,有沒有覺得生命獲得救贖阿?
更多資訊可以上他們的Github(“https://github.com/Masonry/Masonry")上看,我上面這些介紹只是初階中的初階而已。
歡迎討論。
^3: Learn to prioritize(“https://github.com/Masonry/Masonry#learn-to-prioritize")