打開Masonry的源代碼,能夠發現兩個屬性php
/*ios
/**git
* Sets the NSLayoutConstraint multiplier propertygithub
*/框架
- (MASConstraint * (^)(CGFloat multiplier))multipliedBy;less
/**dom
* Sets the NSLayoutConstraint multiplier to 1.0/dividedByiphone
*/ide
- (MASConstraint * (^)(CGFloat divider))dividedBy;函數
*/
multipler屬性表示約束值爲約束對象的乘因數, dividedBy屬性表示約束值爲約束對象的除因數,可用於設置view的寬高比
這兩個屬性能夠設置視圖中的寬高比例
上代碼。。
[aview makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view);
make.bottom.mas_equalTo(self.view);
make.right.mas_equalTo(WeSelf.InputYuYinbtn.left);
make.height.mas_equalTo(aview.width).multipliedBy(0.6);// 高/寬 == 0.6
}];
自動佈局最重要的是約束:UI元素間關係的數學表達式。約束包括尺寸、由優先級和閾值管理的相對位置。它們是添加劑,可能致使約束衝突 、約束不足形成佈局沒法肯定 。這兩種狀況都會產生異常。
setNeedsLayout
:告知頁面須要更新,可是不會馬上開始更新。執行後會馬上調用layoutSubviews。layoutIfNeeded
:告知頁面佈局馬上更新。因此通常都會和setNeedsLayout一塊兒使用。若是但願馬上生成新的frame須要調用此方法,利用這點通常佈局動畫能夠在更新佈局後直接使用這個方法讓動畫生效。layoutSubviews
:系統重寫佈局setNeedsUpdateConstraints
:告知須要更新約束,可是不會馬上開始updateConstraintsIfNeeded
:告知馬上更新約束updateConstraints
:系統更新約束1. 基本使用
mas_makeConstraints
:添加約束mas_updateConstraints
:更新約束、亦可添加新約束mas_remakeConstraints
:重置以前的約束
multipler
屬性表示約束值爲約束對象的乘因數, dividedBy
屬性表示約束值爲約束對象的除因數,可用於設置view
的寬高比
// 進行屏幕的適配的時候,每每須要根據屏幕寬度來適配一個相應的高度,在此推薦使用以下約束的方式來進行控件的適配 [self.topView addSubview:self.topInnerView]; [self.topInnerView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(self.topView.mas_height).dividedBy(3); make.width.and.height.lessThanOrEqualTo(self.topView); make.width.and.height.equalTo(self.topView).with.priorityLow(); make.center.equalTo(self.topView); }];
priorityLow()
設置約束優先級#define MAS_SHORTHAND_GLOBALS
使用全局宏定義,可使equalTo
等效於mas_equalTo
#define MAS_SHORTHAND
使用全局宏定義, 能夠在調用masonry方法的時候不使用mas_
前綴// 這裏注意到一個地方,就是當使用了這個全局宏定義以後,發現能夠有個類`NSArray+MASAdditions.h`,看了以後發現能夠 self.buttonViews = @[ raiseButton, lowerButton, centerButton ]; // 以後能夠在updateConstraints 方法中 - (void)updateConstraints { [self.buttonViews updateConstraints:^(MASConstraintMaker *make) { make.baseline.equalTo(self.mas_centerY).with.offset(self.offset); }]; [super updateConstraints]; }
// 建立視圖約束 [blueView mas_makeConstraints:^(MASConstraintMaker *make) { self.animatableConstraint = make.edges.equalTo(superview).insets(paddingInsets).priorityLow(); ]]; // 更改約束 (另外一處方法中) UIEdgeInsets paddingInsets = UIEdgeInsetsMake(padding, padding, padding, padding); self.animatableConstraint.insets = paddingInsets; [self layoutIfNeeded];
debug
模式: // 對某個view添加key值 greenView.mas_key = @"greenView"; // 或者以下順序 MASAttachKeys(greenView, redView, blueView, superview); // 一樣的對每條約束亦能夠添加key make.height.greaterThanOrEqualTo(@5000).key(@"ConstantConstraint");
preferredMaxLayoutWidth
: 多行label的約束問題// 已經確認好了位置 // 在layoutSubviews中確認label的preferredMaxLayoutWidth值 - (void)layoutSubviews { [super layoutSubviews]; // 你必須在 [super layoutSubviews] 調用以後,longLabel的frame有值以後設置preferredMaxLayoutWidth self.longLabel.preferredMaxLayoutWidth = self.frame.size.width-100; // 設置preferredLayoutWidth後,須要從新佈局 [super layoutSubviews]; }
scrollView
使用約束的問題:原理經過一個contentView來約束scrollView的contentSize大小,也就是說以子控件的約束條件,來控制父視圖的大小// 1. 控制scrollView大小(顯示區域) [self.scrollView makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); }]; // 2. 添加一個contentView到scrollView,而且添加好約束條件 [contentView makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.scrollView); // 注意到此處的寬度約束條件,這個寬度的約束條件是比添加項 make.width.equalTo(self.scrollView); }]; // 3. 對contentView的子控件作好約束,達到能夠控制contentView的大小
/** * 多個控件固定間隔的等間隔排列,變化的是控件的長度或者寬度值 * * @param axisType 軸線方向 * @param fixedSpacing 間隔大小 * @param leadSpacing 頭部間隔 * @param tailSpacing 尾部間隔 */ - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing l eadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; /** * 多個固定大小的控件的等間隔排列,變化的是間隔的空隙 * * @param axisType 軸線方向 * @param fixedItemLength 每一個控件的固定長度或者寬度值 * @param leadSpacing 頭部間隔 * @param tailSpacing 尾部間隔 */ - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;
使用方法很簡單,由於它是NSArray的類擴展:
// 建立水平排列圖標 arr中放置了2個或連個以上的初始化後的控件 // alongAxis 軸線方向 固定間隔 頭部間隔 尾部間隔 [arr mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:20 leadSpacing:5 tailSpacing:5]; [arr makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(@60); make.height.equalTo(@60); }];
2. 注意事項
addSubview
以後,才能給視圖添加約束updateConstraints
內調用的時候,你就須要在此調用此方法,由於 updateConstraints
方法是須要觸發的// 調用在view 內部,而不是viewcontroller + (BOOL)requiresConstraintBasedLayout { return YES; } /** * 蘋果推薦 約束 增長和修改 放在此方法種 */ - (void)updateConstraints { [self.growingButton updateConstraints:^(MASConstraintMaker *make) { make.center.equalTo(self); make.width.equalTo(@(self.buttonSize.width)).priorityLow(); make.height.equalTo(@(self.buttonSize.height)).priorityLow(); make.width.lessThanOrEqualTo(self); make.height.lessThanOrEqualTo(self); }]; //最後記得回調super方法 [super updateConstraints]; }
// 通知須要更新約束,可是不當即執行 [self setNeedsUpdateConstraints]; // 當即更新約束,以執行動態變換 // update constraints now so we can animate the change [self updateConstraintsIfNeeded]; // 執行動畫效果, 設置動畫時間 [UIView animateWithDuration:0.4 animations:^{ [self layoutIfNeeded]; }];
1
|
MagicNumber -> autoresizingMask -> autolayout
|
以上是純手寫代碼所經歷的關於頁面佈局的三個時期
在iphone1-iphone3gs時代 window的size固定爲(320,480) 咱們只須要簡單計算一下相對位置就行了
在iphone4-iphone4s時代 蘋果推出了retina屏 可是給了碼農們很是大的福利:window的size不變
在iphone5-iphone5s時代 window的size變了(320,568) 這時autoresizingMask派上了用場(爲啥這時候不用Autolayout? 由於還要支持ios5唄) 簡單的適配一下便可
在iphone6+時代 window的width也發生了變化(相對5和5s的屏幕比例沒有變化) 終因而時候拋棄autoresizingMask改用autolayout了(不用支持ios5了 相對於屏幕適配的多樣性來講autoresizingMask也已通過時了)
那如何快速的上手autolayout呢? 說實話 當年ios6推出的同時新增了autolayout的特性 我看了一下官方文檔和demo 就立馬拋棄到一邊了 由於實在過於的繁瑣和囉嗦(有過經驗的朋友確定有同感)
直到iPhone6發佈以後 我知道使用autolayout勢在必行了 這時想起了之前在瀏覽Github看到過的一個第三方庫Masonry 在花了幾個小時的研究使用後 我就將autolayout掌握了(重點是我並無學習任何的官方文檔或者其餘的關於autolayout的知識) 這就是我爲何要寫下這篇文章來推薦它的緣由.
介紹
Masonry 源碼:https://github.com/Masonry/Masonry
Masonry是一個輕量級的佈局框架 擁有本身的描述語法 採用更優雅的鏈式語法封裝自動佈局 簡潔明瞭 並具備高可讀性 並且同時支持 iOS 和 Max OS X。
咱們先來看一段官方的sample code來認識一下Masonry
1
2
3
|
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).
with
.insets(padding);
}];
|
看到block裏面的那句話: make edges equalTo superview with insets
經過鏈式的天然語言 就把view1給autolayout好了 是否是簡單易懂?
使用
看一下Masonry支持哪一些屬性
1
2
3
4
5
6
7
8
9
10
11
|
@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;
|
這些屬性與NSLayoutAttrubute的對照表以下
其中leading與left trailing與right 在正常狀況下是等價的 可是當一些佈局是從右至左時(好比阿拉伯文?沒有相似的經驗) 則會對調 換句話說就是基本能夠不理不用 用left和right就行了
在ios8發佈後 又新增了一堆奇奇怪怪的屬性(有興趣的朋友能夠去瞅瞅) Masonry暫時還不支持(不過你要支持ios6,ios7 就不必去管那麼多了)
在講實例以前 先介紹一個MACRO
1
|
#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self;
|
快速的定義一個weakSelf 固然是用於block裏面啦 下面進入正題(爲了方便 咱們測試的superView都是一個size爲(300,300)的UIView)
下面 經過一些簡單的實例來簡單介紹如何輕鬆愉快的使用Masonry:
1. [基礎] 居中顯示一個view
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
- (void)viewDidLoad
{
[
super
viewDidLoad];
// Do any additional setup after loading the view.
WS(ws);
UIView *sv = [UIView
new
];
[sv showPlaceHolder];
sv.backgroundColor = [UIColor blackColor];
[self.view addSubview:sv];
[sv mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(ws.view);
make.size.mas_equalTo(CGSizeMake(300, 300));
}];
}
|
代碼效果
使用我之間寫的MMPlaceHolder 能夠看到superview已經按照咱們預期居中而且設置成了適當的大小
那麼先看看這幾行代碼
1
2
3
4
5
6
7
8
9
10
11
12
|
//今後之後基本能夠拋棄CGRectMake了
UIView *sv = [UIView
new
];
//在作autoLayout以前 必定要先將view添加到superview上 不然會報錯
[self.view addSubview:sv];
//mas_makeConstraints就是Masonry的autolayout添加函數 將所需的約束添加到block中行了
[sv mas_makeConstraints:^(MASConstraintMaker *make) {
//將sv居中(很容易理解吧?)
make.center.equalTo(ws.view);
//將size設置成(300,300)
make.size.mas_equalTo(CGSizeMake(300, 300));
}];
|
這裏有兩個問題要分解一下
首先在Masonry中可以添加autolayout約束有三個函數
1
2
3
4
5
6
7
8
9
|
- (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 則會清除以前的全部約束 僅保留最新的約束
三種函數善加利用 就能夠應對各類狀況了
*/
|
其次 equalTo 和 mas_equalTo的區別在哪裏呢? 其實 mas_equalTo是一個MACRO
1
2
3
4
|
#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__)))
#define mas_greaterThanOrEqualTo(...) greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
#define mas_lessThanOrEqualTo(...) lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
#define mas_offset(...) valueOffset(MASBoxValue((__VA_ARGS__)))
|
能夠看到 mas_equalTo只是對其參數進行了一個BOX操做(裝箱) MASBoxValue的定義具體能夠看看源代碼 太長就不貼出來了
所支持的類型 除了NSNumber支持的那些數值類型以外 就只支持CGPoint CGSize UIEdgeInsets
介紹完這幾個問題 咱們就繼續往下了 PS:剛纔定義的sv會成爲咱們接下來全部sample的superView
2. [初級] 讓一個view略小於其superView(邊距爲10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
UIView *sv1 = [UIView
new
];
[sv1 showPlaceHolder];
sv1.backgroundColor = [UIColor redColor];
[sv addSubview:sv1];
[sv1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(sv).
with
.insets(UIEdgeInsetsMake(10, 10, 10, 10));
/* 等價於
make.top.equalTo(sv).with.offset(10);
make.left.equalTo(sv).with.offset(10);
make.bottom.equalTo(sv).with.offset(-10);
make.right.equalTo(sv).with.offset(-10);
*/
/* 也等價於
make.top.left.bottom.and.right.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
*/
}];
|
代碼效果
能夠看到 edges 其實就是top,left,bottom,right的一個簡化 分開寫也能夠 一句話更省事
那麼爲何bottom和right裏的offset是負數呢? 由於這裏計算的是絕對的數值 計算的bottom須要小魚sv的底部高度 因此要-10 同理用於right
這裏有意思的地方是and和with 其實這兩個函數什麼事情都沒作
1
2
3
4
5
6
|
- (MASConstraint *)
with
{
return
self;
}
- (MASConstraint *)and {
return
self;
}
|
可是用在這種鏈式語法中 就很是的巧妙和易懂 不得不佩服做者的心思(雖然我如今基本都會省略)
3. [初級] 讓兩個高度爲150的view垂直居中且等寬且等間隔排列 間隔爲10(自動計算其寬度)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int padding1 = 10;
[sv2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(sv.mas_centerY);
make.left.equalTo(sv.mas_left).
with
.offset(padding1);
make.right.equalTo(sv3.mas_left).
with
.offset(-padding1);
make.height.mas_equalTo(@150);
make.width.equalTo(sv3);
}];
[sv3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(sv.mas_centerY);
make.left.equalTo(sv2.mas_right).
with
.offset(padding1);
make.right.equalTo(sv.mas_right).
with
.offset(-padding1);
make.height.mas_equalTo(@150);
make.width.equalTo(sv2);
}];
|
代碼效果
這裏咱們在兩個子view之間互相設置的約束 能夠看到他們的寬度在約束下自動的被計算出來了
4. [中級] 在UIScrollView順序排列一些view並自動計算contentSize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
UIScrollView *scrollView = [UIScrollView
new
];
scrollView.backgroundColor = [UIColor whiteColor];
[sv addSubview:scrollView];
[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(sv).
with
.insets(UIEdgeInsetsMake(5,5,5,5));
}];
UIView *container = [UIView
new
];
[scrollView addSubview:container];
[container mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scrollView);
make.width.equalTo(scrollView);
}];
int count = 10;
UIView *lastView = nil;
for
( int i = 1 ; i <= count ; ++i )
{
UIView *subv = [UIView
new
];
[container addSubview:subv];
subv.backgroundColor = [UIColor colorWithHue:( arc4random() % 256 / 256.0 )
saturation:( arc4random() % 128 / 256.0 ) + 0.5
brightness:( arc4random() % 128 / 256.0 ) + 0.5
alpha:1];
[subv mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.and.right.equalTo(container);
make.height.mas_equalTo(@(20*i));
if
( lastView )
{
make.top.mas_equalTo(lastView.mas_bottom);
}
else
{
make.top.mas_equalTo(container.mas_top);
}
}];
lastView = subv;
}
[container mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(lastView.mas_bottom);
}];
|
頭部效果
尾部效果
從scrollView的scrollIndicator能夠看出 scrollView的內部已如咱們所想排列好了
這裏的關鍵就在於container這個view起到了一箇中間層的做用 可以自動的計算uiscrollView的contentSize
5. [高級] 橫向或者縱向等間隙的排列一組view
很遺憾 autoLayout並無直接提供等間隙排列的方法(Masonry的官方demo中也沒有對應的案例) 可是參考案例3 咱們能夠經過一個小技巧來實現這個目的 爲此我寫了一個Category
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
@implementation UIView(Masonry_LJC)
- (void) distributeSpacingHorizontallyWith:(NSArray*)views
{
NSMutableArray *spaces = [NSMutableArray arrayWithCapacity:views.count+1];
for
( int i = 0 ; i < views.count+1 ; ++i )
{
UIView *v = [UIView
new
];
[spaces addObject:v];
[self addSubview:v];
[v mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(v.mas_height);
}];
}
UIView *v0 = spaces[0];
__weak __typeof(&*self)ws = self;
[v0 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(ws.mas_left);
make.centerY.equalTo(((UIView*)views[0]).mas_centerY);
}];
UIView *lastSpace = v0;
for
( int i = 0 ; i < views.count; ++i )
{
UIView *obj = views[i];
UIView *space = spaces[i+1];
[obj mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(lastSpace.mas_right);
}];
[space mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(obj.mas_right);
make.centerY.equalTo(obj.mas_centerY);
make.width.equalTo(v0);
}];
lastSpace = space;
}
[lastSpace mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(ws.mas_right);
}];
}
- (void) distributeSpacingVerticallyWith:(NSArray*)views
{
NSMutableArray *spaces = [NSMutableArray arrayWithCapacity:views.count+1];
for
( int i = 0 ; i < views.count+1 ; ++i )
{
UIView *v = [UIView
new
];
[spaces addObject:v];
[self addSubview:v];
[v mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(v.mas_height);
}];
}
UIView *v0 = spaces[0];
__weak __typeof(&*self)ws = self;
[v0 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(ws.mas_top);
make.centerX.equalTo(((UIView*)views[0]).mas_centerX);
}];
UIView *lastSpace = v0;
for
( int i = 0 ; i < views.count; ++i )
{
UIView *obj = views[i];
UIView *space = spaces[i+1];
[obj mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(lastSpace.mas_bottom);
}];
[space mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(obj.mas_bottom);
make.centerX.equalTo(obj.mas_centerX);
make.height.equalTo(v0);
}];
lastSpace = space;
}
[lastSpace mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(ws.mas_bottom);
}];
}
@end
|
簡單的來測試一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
UIView *sv11 = [UIView
new
];
UIView *sv12 = [UIView
new
];
UIView *sv13 = [UIView
new
];
UIView *sv21 = [UIView
new
];
UIView *sv31 = [UIView
new
];
sv11.backgroundColor = [UIColor redColor];
sv12.backgroundColor = [UIColor redColor];
sv13.backgroundColor = [UIColor redColor];
sv21.backgroundColor = [UIColor redColor];
sv31.backgroundColor = [UIColor redColor];
[sv addSubview:sv11];
[sv addSubview:sv12];
[sv addSubview:sv13];
[sv addSubview:sv21];
[sv addSubview:sv31];
//給予不一樣的大小 測試效果
[sv11 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(@[sv12,sv13]);
make.centerX.equalTo(@[sv21,sv31]);
make.size.mas_equalTo(CGSizeMake(40, 40));
}];
[sv12 mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(70, 20));
}];
[sv13 mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(50, 50));
}];
[sv21 mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(50, 20));
}];
[sv31 mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(40, 60));
}];
[sv distributeSpacingHorizontallyWith:@[sv11,sv12,sv13]];
[sv distributeSpacingVerticallyWith:@[sv11,sv21,sv31]];
[sv showPlaceHolderWithAllSubviews];
[sv hidePlaceHolder];
|
代碼效果
perfect! 簡潔明瞭的達到了咱們所要的效果
這裏所用的技巧就是 使用空白的佔位view來填充咱們目標view的旁邊 這點經過圖上的空白標註能夠看出來
小結
經過以上5個案例 我以爲已經把Masonry的經常使用功能介紹得差很少了 若是你以爲意猶未盡呢 請下載官方的demo來學習
總而言之 Masonry是一個很是優秀的autolayout庫 可以節省大量的開發和學習時間 尤爲適合我這種純代碼的iOSer 在iPhone6發佈後引起的適配潮中 Masonry必定能夠助你一臂之力 :)
約束
,參照
frame
約束
,最終仍是爲了肯定其位置
與尺寸
位置
,尺寸
這兩個必要條件優先級
的約束優先級
會在例子中說明其用處
先添加四個View
UIView *redView = [[UIView alloc]init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; UIView *blueView = [[UIView alloc]init]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; UIView *yellow = [[UIView alloc]init]; yellow.backgroundColor = [UIColor yellowColor]; [self.view addSubview:yellow]; UIView *green = [[UIView alloc]init]; green.backgroundColor = [UIColor greenColor]; [self.view addSubview:green];
mas_makeConstraints
這個方法使左邊等於self.view的左邊,間距爲0
and
與with
其實就是get調用者自己,裏面僅僅是return self[redView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view.mas_left).offset(0);//使左邊等於self.view的左邊,間距爲0 make.top.equalTo(self.view.mas_top).offset(0);//使頂部與self.view的間距爲0 make.width.equalTo(self.view.mas_width).multipliedBy(0.5);//設置寬度爲self.view的一半,multipliedBy是倍數的意思,也就是,使寬度等於self.view寬度的0.5倍 make.height.equalTo(self.view.mas_height).multipliedBy(0.5);//設置高度爲self.view高度的一半 }];
錨點
,來添加約束,肯定自身的位置
與尺寸
圖1
中的blueView的效果,咱們應當怎樣添加約束呢?[blueView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.and.height.equalTo(redView);//使寬高等於redView make.top.equalTo(redView.mas_top);//與redView頂部對齊 make.leading.equalTo(redView.mas_right);//與redView的間距爲0 }];
位置
與尺寸
[yellow mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(redView);//與redView左對齊 make.top.equalTo(redView.mas_bottom);//與redView底部間距爲0 make.width.and.height.equalTo(redView);//與redView寬高相等 }]; [green mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(yellow.mas_right);//與yellow右邊間距爲0 make.top.equalTo(blueView.mas_bottom);//與blueView底部間距爲0 make.width.and.height.equalTo(redView);//與redView等寬高 }];
尺寸
的例子,或者是固定位置
的例子,我怕誤導你們認爲Autolayout是很是死板的,必須把每一個控件的約束添加到知足位置
與尺寸
,再去添加其餘控件的約束,這樣纔不會出錯位置
與尺寸
,可是有時這兩個必須條件能夠利用相對
來知足
相對
概念//代碼中View的順序與圖中從左到右的View的順序一致 //例子中,惟一不肯定的就是灰色View的寬度,咱們先把肯定的約束給一個一個的添加上來 //灰1左間距、高度、垂直位置(由於和紅1底部對齊)是肯定的,添加約束 [gray1 mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(20); make.leading.equalTo(self.view.mas_leading).offset(0); make.bottom.equalTo(red1.mas_bottom); }]; //紅1,寬高、左間距、底間距是肯定的,添加約束 [red1 mas_makeConstraints:^(MASConstraintMaker *make) { make.width.mas_equalTo(100); make.height.mas_equalTo(50); make.left.equalTo(gray1.mas_right); make.bottom.equalTo(self.view.mas_bottom).offset(-50); }]; //灰2,左間距、高度、垂直位置是肯定的,寬度要與灰1一致,是爲了能均勻填充,添加約束 [gray2 mas_makeConstraints:^(MASConstraintMaker *make) { make.height.and.width.equalTo(gray1); make.leading.equalTo(red1.mas_right); make.bottom.equalTo(red1.mas_bottom); }]; //紅2,寬高、左間距、底間距是肯定的,添加約束 [red2 mas_makeConstraints:^(MASConstraintMaker *make) { make.height.and.width.equalTo(red1); make.leading.equalTo(gray2.mas_right); make.bottom.equalTo(red1.mas_bottom); }]; //灰3,左間距、右間距、高度、垂直位置是肯定的,添加約束 [gray3 mas_makeConstraints:^(MASConstraintMaker *make) { make.height.and.width.equalTo(gray1); make.leading.equalTo(red2.mas_right); make.trailing.equalTo(self.view.mas_right); make.bottom.equalTo(red1.mas_bottom); }];
相對
,紅色方塊寬度是固定的,那麼水平方向上的間距就須要剩下的三個灰色方塊去填充,當界面橫屏時,三個灰色方塊爲了相對
自身寬度要相同,相對
紅色邊界,self.view邊界,間距保持爲0,那麼就得犧牲自身寬度的穩定,去維持這些相對
的約束UIView *redView = [[UIView alloc]init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; UIView *greenView = [[UIView alloc]init]; greenView.backgroundColor = [UIColor greenColor]; [self.view addSubview:greenView]; UIView *blueView = [[UIView alloc]init]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; [redView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view.mas_left).offset(20); make.bottom.equalTo(self.view.mas_bottom).offset(-20); make.width.equalTo(self.view.mas_width).multipliedBy(0.2); make.height.equalTo(self.view.mas_height).multipliedBy(0.2); }]; [greenView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(redView.mas_right).offset(20); make.bottom.equalTo(self.view.mas_bottom).offset(-20); make.width.equalTo(self.view.mas_width).multipliedBy(0.2); make.height.equalTo(self.view.mas_height).multipliedBy(0.2); }]; [blueView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(greenView.mas_right).offset(20); make.bottom.equalTo(self.view.mas_bottom).offset(-20); make.width.equalTo(self.view.mas_width).multipliedBy(0.2); make.height.equalTo(self.view.mas_height).multipliedBy(0.2); make.left.equalTo(redView.mas_right).offset(20).priority(250); }];
[self.greenView removeFromSuperview]; [UIView animateWithDuration:1.0f animations:^{ [self.view layoutIfNeeded]; }];