第三方 Masonry約束的使用 less
給Autolayout披上一層漂亮的外衣以後,將其稱爲Masonry,但Masonry的本質仍是Autolayout。能夠理解爲Masonry是對Autolayout的封裝.ide
對於一個約束。他實際表示的是一個不等或者相等關係atom
用Masonry建立一個完整的約束應該是這樣的spa
//view1的左邊距離父View左邊10個點: [view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(view1.superview.mas_left).multipliedBy(1).offset(10); }];
上面的表達式中,咱們能夠看到,make是MASConstraintMaker類型。MASConstraintMaker給咱們提供了22種Attribute類型.net
//Basic Attribute @property (nonatomic, strong, readonly) MASConstraint *left; @property (nonatomic, strong, readonly) MASConstraint *top; @property (nonatomic, strong, readonly) MASConstraint *right; @property (nonatomic, strong, readonly) MASConstraint *bottom; @property (nonatomic, strong, readonly) MASConstraint *leading; @property (nonatomic, strong, readonly) MASConstraint *trailing; @property (nonatomic, strong, readonly) MASConstraint *width; @property (nonatomic, strong, readonly) MASConstraint *height; @property (nonatomic, strong, readonly) MASConstraint *centerX; @property (nonatomic, strong, readonly) MASConstraint *centerY; @property (nonatomic, strong, readonly) MASConstraint *baseline; //Margin Attribute @property (nonatomic, strong, readonly) MASConstraint *leftMargin; @property (nonatomic, strong, readonly) MASConstraint *rightMargin; @property (nonatomic, strong, readonly) MASConstraint *topMargin; @property (nonatomic, strong, readonly) MASConstraint *bottomMargin; @property (nonatomic, strong, readonly) MASConstraint *leadingMargin; @property (nonatomic, strong, readonly) MASConstraint *trailingMargin; @property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins; @property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins; //Convenient Attribute @property (nonatomic, strong, readonly) MASConstraint *edges; @property (nonatomic, strong, readonly) MASConstraint *size; @property (nonatomic, strong, readonly) MASConstraint *center;
Attribute整體來講分爲三大類code
Convenient Attribute實際是基本屬性的組合。好比:edges表示left, right, top, bottom。
下面的兩個代碼實際的意義是同樣的對象
//Convenient Attribute make.edges.insets(edge); //Basic Attribute make.left.right.top.bottom.insets(edge);
前面咱們看到MASConstraintMaker中全部的Attribute都是MASConstraint類型。對於多個Attribute一塊兒寫的表達式:blog
make.left.right.top.bottom.insets(edge);
make.left
返回的已是MASConstraint類型,也就是說right這個Attribute是MASConstraint的屬性。
MASConstraint給咱們提供了19種Attribute:接口
//Basic Attribute @property (nonatomic, strong, readonly) MASConstraint *left; @property (nonatomic, strong, readonly) MASConstraint *top; @property (nonatomic, strong, readonly) MASConstraint *right; @property (nonatomic, strong, readonly) MASConstraint *bottom; @property (nonatomic, strong, readonly) MASConstraint *leading; @property (nonatomic, strong, readonly) MASConstraint *trailing; @property (nonatomic, strong, readonly) MASConstraint *width; @property (nonatomic, strong, readonly) MASConstraint *height; @property (nonatomic, strong, readonly) MASConstraint *centerX; @property (nonatomic, strong, readonly) MASConstraint *centerY; @property (nonatomic, strong, readonly) MASConstraint *baseline; //Margin Attribute @property (nonatomic, strong, readonly) MASConstraint *leftMargin; @property (nonatomic, strong, readonly) MASConstraint *rightMargin; @property (nonatomic, strong, readonly) MASConstraint *topMargin; @property (nonatomic, strong, readonly) MASConstraint *bottomMargin; @property (nonatomic, strong, readonly) MASConstraint *leadingMargin; @property (nonatomic, strong, readonly) MASConstraint *trailingMargin; @property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins; @property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins;
細看一下,MASConstraint中的Attribute和MASConstraintMaker徹底同樣。只是MASConstraintMaker中多了3種Convenient Attribute。ip
二者Attribute的一致,大大的提高了使用的方便性。使用過程當中咱們不用再去區分當前屬性是MASConstraint仍是MASConstraintMaker類型。(事實上沒研究他的類型以前,我都不知道他們分別屬於2種不一樣類的屬性)
咱們能夠看到在.equalTo(view1.superview.mas_left)
裏面,superView也有Attribute。咱們來看看UIView中有哪些Attribute:
// Basic Attribute @property (nonatomic, strong, readonly) MASViewAttribute *mas_left; @property (nonatomic, strong, readonly) MASViewAttribute *mas_top; @property (nonatomic, strong, readonly) MASViewAttribute *mas_right; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom; @property (nonatomic, strong, readonly) MASViewAttribute *mas_leading; @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing; @property (nonatomic, strong, readonly) MASViewAttribute *mas_width; @property (nonatomic, strong, readonly) MASViewAttribute *mas_height; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY; @property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline; // Margin Attribute @property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;
能夠看出,在UIView中的Attribute和MASConstraint中的幾乎如出一轍,只是每個Attribute加了一個mas_前綴。
因爲UIView是系統的類,對其擴展屬性和方法通常都須要添加本身的前綴,避免跟原有屬性和方法衝突。不過他們的意義跟MASConstraint中的Attribute是相同的
約束表示的是2個item之間的關係,在Autolayout中一共定義了3種關係:=, >=, <=,對應到Masonry中:
- (MASConstraint * (^)(id attr))equalTo; - (MASConstraint * (^)(id attr))greaterThanOrEqualTo; - (MASConstraint * (^)(id attr))lessThanOrEqualTo;
相等關係咱們通常用的多。那麼不相等關係咱們何時用呢?
假如我有一個Label。Label的長度不能超出父View,若是label中的文字比較短,我但願是文字有多長,Label就有多長。
因爲label具備IntrinsicContentSize屬性。因此默認狀況下,他是文字有多長,Label就有多長。因此咱們只須要設置Label的長度小於父View便可
[label mas_makeConstraints:^(MASConstraintMaker *make) { make.left.offset(0); make.centerY.offset(0); make.width.lessThanOrEqualTo(label.superview);}];
multiplier表示Attribute前面的乘數。Masonry提供了2種添加multiplier的方法
// Sets the NSLayoutConstraint multiplier property - (MASConstraint * (^)(CGFloat multiplier))multipliedBy; // Sets the NSLayoutConstraint multiplier to 1.0/dividedBy - (MASConstraint * (^)(CGFloat divider))dividedBy;
multipliedBy
: 直接設置乘數
dividedBy
: 設置乘數的倒數 multiplier = 1.0/dividedBy
通常寬或者高的約束使用multiplier比較多
Masonry提供了4種設置constant的方法
//Modifies the NSLayoutConstraint constant,only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - (MASConstraint * (^)(MASEdgeInsets insets))insets; //Modifies the NSLayoutConstraint constant,only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following NSLayoutAttributeWidth, NSLayoutAttributeHeight - (MASConstraint * (^)(CGSize offset))sizeOffset; //Modifies the NSLayoutConstraint constant, only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following NSLayoutAttributeCenterX, NSLayoutAttributeCenterY - (MASConstraint * (^)(CGPoint offset))centerOffset; //Modifies the NSLayoutConstraint constant - (MASConstraint * (^)(CGFloat offset))offset;
insets
: 用來設置left, right, top, bottom。接受MASEdgeInsets類型值
sizeOffset
: 用來設置width, height。接受CGSize類型的值
centerOffset
: 用來設置centerX, centerY。接受CGPoint類型的值
offset
: 能夠用來設置全部的東西。接受CGFloat類型的值
下面全部代碼實際效果是同樣的:
// 完整的 make.left.equalTo(view1.superview.mas_left).offset(0); //省略Attribute的 make.left.equalTo(view1.superview).offset(0); //省略equalTo的 make.left.offset(0); //使用equalTo替代offset的 make.left.equalTo(@0); //終極大招,省略全部的... 惋惜會有warning make.left;
對於這個警告咱們能夠將返回值轉爲空消除:
(void)make.left;
對於約束的設置,Masonry提供了3種方法,分別爲設置約束、更新約束、重寫設置約束
// 設置約束 - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block; // 更新約束 - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block; // 從新設置約束 - (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
mas_makeConstraints
: 初次設置約束使用。
mas_updateConstraints
: 更新約束時使用。若是找不着這條約束,會新增,至關於mas_makeConstraints。
mas_remakeConstraints
: 從新設置約束。先將view上全部約束移除,再新增約束
注意:mas_updateConstraints只能更新已有約束。若是第一次使用的是left, right設置的相對寬度。更新的時候想換成使用width。不能使用mas_updateConstraints,由於已有約束裏面沒有width的約束,新增width以後會跟原有left, right約束衝突。此時應該使用mas_remakeConstraints
假設有View1,view2,view3三個View,咱們想要他們的寬高都等於CGSizeMake(100, 50)。咱們能夠對他們進行批量設置:
NSValue *sizeValue = [NSValue valueWithCGSize:CGSizeMake(100, 50)]; [@[view1,view2,view3] mas_makeConstraints:^(MASConstraintMaker *make) { make.size.equalTo(sizeValue); }];
因爲咱們還要設置view的top,left等位置約束。那可不能夠在設置位置的mas_makeConstraints裏面批量設置寬高呢?實際是能夠的!
//advance set [view1 mas_makeConstraints:^(MASConstraintMaker *make) { (void)make.top.left; make.size.equalTo(@[view2,view3,sizeValue]); }];
不過須要注意的是。設置約束的時候,view必定是已經被addSubview的,不然會拋異常。因此咱們通常在最後一個view上加批量約束
咱們知道約束是有優先級的,Masonry給咱們提供了4個設置優先級的接口:
// Sets the NSLayoutConstraint priority to a float or MASLayoutPriority - (MASConstraint * (^)(MASLayoutPriority priority))priority; // Sets the NSLayoutConstraint priority to MASLayoutPriorityLow - (MASConstraint * (^)())priorityLow; // Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium - (MASConstraint * (^)())priorityMedium; // Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh - (MASConstraint * (^)())priorityHigh;
priority
: 能夠設置任意的優先級,接受的參數是0-1000的數字
priorityLow
: 設置低優先級,優先級爲250
priorityMedium
: 設置中優先級,優先級爲500
priorityHigh
: 設置高優先級,優先級爲750
須要注意的是,使用priorityLow、priorityMedium、priorityHigh的時候。不是.priorityHigh
,而是.priorityHigh()
在寫代碼的時候,可能你會感受有的東西要加mas_前綴,有的東西又不用加,代碼風格不統一,並且加mas_前綴還麻煩。
前面介紹過加mas_前綴主要是在擴展系統類的時候爲了不與原有類衝突,這是Apple推薦的作法。不過目前來講,即便不加mas_前綴,也不會有什麼問題。因此Masonry提供了不加mas_前綴的方法,只須要你定義幾個宏便可。
1, MAS_SHORTHAND
定義MAS_SHORTHAND宏以後。可使用UIView,NSArray中不帶mas_前綴的makeConstraints,updateConstraints,remakeConstraints。以及UIView中不帶mas_前綴的Attribute
2, MAS_SHORTHAND_GLOBALS
默認的equalTo方法只接受id類型的對象。有時候咱們想傳入一個CGFloat, CGSize, UIEdgeInsets等。還須要將其轉化成NSValue對象,比較麻煩。Masonry也考慮到了這種狀況。只須要定義MAS_SHORTHAND_GLOBALS宏。就能夠直接對equalTo傳入基礎類型。Masonry自動轉化成NSValue對象
注意:
#define MAS_SHORTHAND
和#define MAS_SHORTHAND_GLOBALS
這兩個宏要在導入Masonry以前定義