對於iOS 開發來說,很多時候,我們用不到原生的開發語言去開發,使用第三方框架,能幫我們節省很多的時間,而且看起來更加的清晰易懂,VFL 語言看起來和維護起來都比較麻煩,而且出錯率比較高,感謝大神提供的 Masonry 提供的佈局框架。github 地址爲:Masonry github 地址
如果想要使一個 view 離它的 superView 上下左右邊距各爲10的話,如果用 VFL 標記語言,起碼要添加兩個約束,還需要設置 view 的translatesAutoresizingMaskIntoConstraints 等等,最後還要把約束 add 到 superview 上,是不是很麻煩,那看看 Masonry 是怎麼處理的吧
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_top).with.offset(padding.top); //with is an optional semantic filler
make.left.equalTo(self.mas_left).with.offset(padding.left);
make.bottom.equalTo(self.mas_bottom).with.offset(-padding.bottom);
make.right.equalTo(self.mas_right).with.offset(-padding.right);
}];
是不是看起來簡潔大方啊
那麼現在來看看這些基本支持的屬性吧
/**
* The following properties return a new MASViewConstraint
* with the first item set to the makers associated view and the appropriate MASViewAttribute
*/
@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; //文本基線
好了,我們把剛剛的官方示例運用到咱們代碼裏面看看是不是和我們想象的效果是一樣的呢
創建了一個 redview
然後關鍵代碼如下:
///先將控件添加到視圖上 我這裏採用的是懶加載
[self.view addSubview:self.redView];
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_top).with.offset(padding.top); //with is an optional semantic filler
make.left.equalTo(self.view.mas_left).with.offset(padding.left);
make.bottom.equalTo(self.view.mas_bottom).with.offset(-padding.bottom);
make.right.equalTo(self.view.mas_right).with.offset(-padding.right);
}];
運行結果如下
我們可以看到 和我們想象的結果是一樣的,離superView 也就是 self.view 邊距上下左右各爲10
現在我們換一種方式,中心點等於superView的中心,寬是self.view 的 width - 20 高是 self.view 的 height - 20 看看是否也是一樣的效果
主要的代碼如下:
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.view.mas_centerX); //with is an optional semantic filler
make.centerY.mas_equalTo(self.view.mas_centerY);
make.width.mas_equalTo(self.view.frame.size.width - 20);
make.height.mas_equalTo(self.view.frame.size.height - 20);
}];
我們運行會發現,結果是一樣的
這裏我遇見一個問題,當我把
make.centerX.mas_equalTo(self.view.mas_centerX);
make.centerY.mas_equalTo(self.view.mas_centerY);
這兩行替換成
make.centerX.mas_equalTo(self.view.center.x);
make.centerY.mas_equalTo(self.view.center.y);
結果運行效果如下
發現 redview 的起始點居然是以 self.view.center.x+10開始的,所以經過多次嘗試後 發現
make.centerX.mas_equalTo(偏移量)
make.centerX.mas_equalTo(0)表示居中
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
/*
mas_makeConstraints 只負責新增約束 Autolayout不能同時存在兩條針對於同一對象的約束 否則會報錯
mas_updateConstraints 針對上面的情況 會更新在block中出現的約束 不會導致出現兩個相同約束的情況
mas_remakeConstraints 則會清除之前的所有約束 僅保留最新的約束
三種函數善加利用 就可以應對各種情況了
*/
使用到這裏,細心的同學們應該會發現,在使用的時候有一個mas_equalTo和一個 equalTo,那麼兩者之間有什麼區別呢,我們點進去看mas_equalTo 會發現其實是一個宏定義
#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__)))
是對 MASBoxValue 的一層包裝點進去看會發現MASBoxValue對一系列的參數做了包裝 包裝成了NSValue對象和NSNumber對象
在這裏介紹一下 優先級的使用
.priorityHigh <======> UILayoutPriorityDefaultHigh 高優先級
.priorityMedium <========> between high and low 介於高/低之間
.priorityLow <=========> UILayoutPriorityDefaultLow 低優先級
make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();
make.top.equalTo(label.mas_top).with.priority(600);
具體示例代碼如下:
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(self.view.frame.size.width - 20);
make.height.mas_equalTo(self.view.frame.size.height - 20);
///這裏設置了優先級
make.top.mas_equalTo(100).with.priority(600);
make.centerX.mas_equalTo(self.view);
///這裏的優先級比上面 top 的優先級低,所以這個約束會被忽略
make.centerY.mas_equalTo(self.view).with.priority(500);
}];
運行效果如下
等比例自適應
.multipliedBy 允許你指定一個兩個視圖的某個屬性等比例變化
item1.attribute1 = multiplier × item2.attribute2 + constant,此爲約束的計算公式, .multipliedBy本質上是用來限定multiplier的
注意,因爲編程中的座標系從父視圖左上頂點開始,所以指定基於父視圖的left或者top的multiplier是沒有意義的,因爲父視圖的left和top總爲0.
如果你需要一個視圖隨着父視圖的寬度和高度,位置自動變化,你應該同時指定 right,bottom,width,height與父視圖對應屬性的比例(基於某個尺寸下的相對位置計算出的比例),並且constant必須爲0.
// 指定寬度爲父視圖的 1/4.
make.width.equalTo(superview).multipliedBy(0.25);
示例代碼如下
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.view).multipliedBy(0.25);
make.height.mas_equalTo(self.view.frame.size.height - 20);
make.centerX.mas_equalTo(self.view);
make.centerY.mas_equalTo(self.view);
}];
運行結果如下
還有 Masonry 使用了很多簡潔的語法使代碼量減少
1.edges 邊界
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(40, 40, 40, 40));
}];
運行結果如下
2.size 尺寸
示例代碼如下:
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(0);
make.size.equalTo(self.view).sizeOffset(CGSizeMake(-200, -200));
}];
運行結果如下
我們會發現 這個 redview 的 size 等於 self.view的寬 高 各減去200
好了 masonry 的使用學習方法就暫且告一段落,日後有複雜的佈局使用到 masonry 來佈局的話,我們可以繼續貼出代碼來分析與佈局哦