Masonry支持的屬性:
/// 左側(cè)
@property (nonatomic, strong, readonly) MASConstraint *left;
/// 上側(cè)
@property (nonatomic, strong, readonly) MASConstraint *top;
/// 右側(cè)
@property (nonatomic, strong, readonly) MASConstraint *right;
/// 下側(cè)
@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;
/// 橫向中點(diǎn)
@property (nonatomic, strong, readonly) MASConstraint *centerX;
/// 縱向中點(diǎn)
@property (nonatomic, strong, readonly) MASConstraint *centerY;
/// 文本基線
@property (nonatomic, strong, readonly) MASConstraint *baseline;
//其中l(wèi)eading與left潮剪,trailing與right 在正常情況下是等價的 但是當(dāng)一些布局是從右至左時(比如阿拉伯文?沒有類似的經(jīng)驗) 則會對調(diào) 換句話說就是基本可以不理不用 用left和right就好了登夫。
/// 距離邊框的距離登下,等同于選中Storyboard的Constrain to margins后加約束
@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;
// 在Masonry的源碼中我們可以看到他們對應(yīng)的NSLayoutAttribute的屬性對應(yīng)如下
- (MASConstraint *)left {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
- (MASConstraint *)top {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
}
- (MASConstraint *)right {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight];
}
- (MASConstraint *)bottom {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom];
}
- (MASConstraint *)leading {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
}
- (MASConstraint *)trailing {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing];
}
- (MASConstraint *)width {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
}
- (MASConstraint *)height {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
}
- (MASConstraint *)centerX {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX];
}
- (MASConstraint *)centerY {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY];
}
- (MASConstraint *)baseline {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline];
}
- (MASConstraint *)leftMargin {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin];
}
- (MASConstraint *)rightMargin {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin];
}
- (MASConstraint *)topMargin {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin];
}
- (MASConstraint *)bottomMargin {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin];
}
- (MASConstraint *)leadingMargin {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin];
}
- (MASConstraint *)trailingMargin {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin];
}
- (MASConstraint *)centerXWithinMargins {
? ? return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins];
}
關(guān)鍵詞
make ? ? ? ? ? ? ? ? ? 需要添加約束的對象
and ? ? ? ? ? ? ? ? ? ? ?無具體意義的語句連貫詞
with ? ? ? ? ? ? ? ? ? ? 無具體意義的語句連貫詞
offset ? ? ? ? ? ? ? ? ? 邊距
equalTo() ? ? ? ? ? ? ?參數(shù)是對象類型算色,一般是視圖對象或者mas_width這樣的坐標(biāo)系對象
mas_equalTo() ? ? ?和上面功能相同总珠,參數(shù)可以傳遞基礎(chǔ)數(shù)據(jù)類型對象,可以理解為比上面的API更強(qiáng)大
width() ? ? ? ? ? ? ? ? ? 用來表示寬度祟绊,例如代表view的寬度
mas_width() ? ? ? ? ? 用來獲取寬度的值弓叛。和上面的區(qū)別在于,一個代表某個坐標(biāo)系對象灾茁,一個用來獲取坐標(biāo)系對象的值
multipliedBy ? ? ? ? ? 倍數(shù)
舉例:make.width.equalTo(self.view.mas_width).multipliedBy(0.5);//設(shè)置寬度為self.view的一半窜觉,multipliedBy是倍數(shù)的意思谷炸,也就是,使寬度等于self.view寬度的0.5倍
?分類
size????????尺寸禀挫,包含(wdith,height)????????make.size.mas_equalTo(CGSizeMake(300, 300));
edges????邊距旬陡,包含(top,left,right,bottom)????????
make.edges.equalTo(_blackView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
可以寫成
make.top.equalTo(_blackView).with.offset(10);? ? ???
make.left.equalTo(_blackView).with.offset(10);? ???
make.bottom.equalTo(_blackView).with.offset(-10);? ???
make.right.equalTo(_blackView).with.offset(-10);
或者?
make.top.left.bottom.and.right.equalTo(_blackView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
center????中心,包含(centerX,centerY)????????make.center.equalTo(self.view);
最常用的三種加約束的方式:
//mas_makeConstraints 只負(fù)責(zé)新增約束 Autolayout不能同時存在兩條針對于同一對象的約束 否則會報錯
?- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
//mas_updateConstraints 針對上面的情況 會更新在block中出現(xiàn)的約束 不會導(dǎo)致出現(xiàn)兩個相同約束的情況
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
//mas_remakeConstraints 則會清除之前的所有約束 僅保留最新的約束
- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
更新約束和布局
關(guān)于更新約束布局相關(guān)的API语婴,主要用以下四個API:
-(void)updateConstraintsIfNeeded調(diào)用此方法季惩,如果有標(biāo)記為需要重新布局的約束,則立即進(jìn)行重新布局腻格,內(nèi)部會調(diào)用updateConstraints方法
-(void)updateConstraints??????????重寫此方法画拾,內(nèi)部實現(xiàn)自定義布局過程
-(BOOL)needsUpdateConstraints?????當(dāng)前是否需要重新布局,內(nèi)部會判斷當(dāng)前有沒有被標(biāo)記的約束
-(void)setNeedsUpdateConstraints??標(biāo)記需要進(jìn)行重新布局
關(guān)于UIView重新布局相關(guān)的API菜职,主要用以下三個API:
-(void)setNeedsLayout??標(biāo)記為需要重新布局
-(void)layoutIfNeeded查看當(dāng)前視圖是否被標(biāo)記需要重新布局青抛,有則在內(nèi)部調(diào)用layoutSubviews方法進(jìn)行重新布局
-(void)layoutSubviews??重寫當(dāng)前方法,在內(nèi)部完成重新布局操作
實例:要給一個視圖加約束為距父視圖上下左右邊距都為10 內(nèi)邊距
// 添加約束酬核,不需要設(shè)置frame
UIView *subView = [[UIView alloc]init];
? subView.backgroundColor = [UIColor blackColor];
// 添加父視圖蜜另,視圖添加完成后才能進(jìn)行布局
?[self.view addSubview:subView];
CGFloat margin = 10;
//第一種:top、left嫡意、right举瑰、bottom一個一個賦值
?[subView mas_makeConstraints:^(MASConstraintMaker *make) {
????????// 距離左邊10
? ? ? ? // make:相當(dāng)于你要布局的視圖
? ? ? ? // equalTo(參照視圖對象),如果參照視圖是self.view,可以不設(shè)置參照視圖的屬性
? ? ? ? // offset(距離數(shù)值)
?????????make.left.equalTo(self.view).offset(margin);
?????????make.right.equalTo(self.view).offset(-margin);// 距離右邊10
? ? ? ? make.top.equalTo(self.view).offset(margin);// 距離上邊10
? ? ? ? make.bottom.equalTo(self.view).offset(-margin);// 距離下邊10
? ? }];
第二種:top蔬螟、left此迅、right、bottom一起賦值 設(shè)置UIEdgeInsetsMake賦值
[subView mas_makeConstraints:^(MASConstraintMaker *make) {
?????make.top.left.bottom.and.right.equalTo(self.view).with.insets(UIEdgeInsetsMake(margin, margin, -margin, -margin));
}];
第三種:設(shè)置edges的值
// 設(shè)置距離參照視圖的內(nèi)邊距 (上左下右)
UIEdgeInsets padding = UIEdgeInsetsMake(10,10,10,10);
[label2 mas_makeConstraints:^(MASConstraintMaker *make) {
? ? ? ? // 設(shè)置約束視圖的邊界距離self.view的邊界值? ? ? ??
????????make.edges.equalTo(self.view).insets(padding);
?? ?}];
#pragma mark 兩個視圖左右排開間距是10
- (void)addTwoOrangeColorView
{
??? //定義邊距為10
??? int padding1 = 10;
?????_orangeView1 = [UIView new];
??? _orangeView1.backgroundColor = [UIColor orangeColor];
??? [self.view addSubview:_orangeView1];
?????_orangeView2 = [UIView new];
??? _orangeView2.backgroundColor = [UIColor orangeColor];
??? [self.view addSubview:_orangeView2];
?????[_orangeView1 mas_makeConstraints:^(MASConstraintMaker *make) {
??????? make.centerY.mas_equalTo(self.view.mas_centerY);
??????? make.left.equalTo(self.view.mas_left).with.offset(padding1);
??????? make.right.equalTo(_orangeView2.mas_left).with.offset(-padding1);
??????? make.height.mas_equalTo(@150);
??????? make.width.equalTo(_orangeView2);
??? }];
?????[_orangeView2 mas_makeConstraints:^(MASConstraintMaker *make) {
??????? make.centerY.mas_equalTo(self.view.mas_centerY);
??????? make.left.equalTo(_orangeView1.mas_right).with.offset(padding1);
??????? make.right.equalTo(self.view.mas_right).with.offset(-padding1);
??????? make.height.mas_equalTo(@150);
??????? make.width.equalTo(_orangeView1);
??? }];
}
UIScrollView自動布局
創(chuàng)建一個containerView內(nèi)容視圖旧巾,并添加到UIScrollView上作為子視圖耸序。UIScrollView原來的子視圖都添加到containerView上,并且和這個視圖設(shè)置約束鲁猩。
因為對UIScrollView進(jìn)行addSubview操作的時候坎怪,本質(zhì)上是往其contentView上添加。也就是containerView的父視圖是contentView廓握,通過containerView撐起contentView視圖的大小搅窿,以此來實現(xiàn)動態(tài)改變contentSize。
#pragma mark 添加滑動視圖
- (void)addScrolView
{
??? _scrolView = [UIScrollView new];
??? _scrolView.backgroundColor = [UIColor whiteColor];
??? [_blackView addSubview:_scrolView];
??? [_scrolView mas_makeConstraints:^(MASConstraintMaker *make) {
??????? make.edges.equalTo(_blackView).with.insets(UIEdgeInsetsMake(5, 5, 5, 5));
??? }];
??? UIView * container = [UIView new];
??? [_scrolView addSubview:container];
??? [container mas_makeConstraints:^(MASConstraintMaker *make) {
??????? make.edges.equalTo(_scrolView);
??????? make.width.equalTo(_scrolView);
??? }];
??? int count = 10;
??? UIView * lastView = nil;
??? for (int i = 0; i <= count; i ++)
??? {
??????? UIView * subView = [UIView new];
??????? [container addSubview:subView];
??????? subView.backgroundColor = [UIColor colorWithHue:(arc4random() % 156 / 256.0) saturation:(arc4random() % 128 / 256.0) brightness:(arc4random() % 128 / 256.0) alpha:1];
??????? [subView mas_makeConstraints:^(MASConstraintMaker *make) {
??????????? make.left.and.right.equalTo(container);
??????????? make.height.equalTo(@(20*i));
??????????? if (lastView) {
??????????????? make.top.mas_equalTo(lastView.mas_bottom);
??????????? }
??????????? else
??????????? {
??????????????? make.top.mas_equalTo(container.mas_top);
??????????? }
??????? }];
??????? lastView = subView;
??? }
??? [container mas_makeConstraints:^(MASConstraintMaker *make) {
??????? make.bottom.equalTo(lastView.mas_bottom);
??? }];
}
大于等于和小于等于某個值的約束
?[self.textLabel?mas_makeConstraints:^(MASConstraintMaker *make)?{????
make.center.equalTo(self.view);??
??// 設(shè)置寬度小于等于200????
make.width.lessThanOrEqualTo(@200);????
// 設(shè)置高度大于等于10????
make.height.greaterThanOrEqualTo(@(10));
}];?
設(shè)置約束優(yōu)先級
/**?
Masonry為我們提供了三個默認(rèn)的方法隙券,priorityLow()男应、priorityMedium()、priorityHigh()是尔,這三個方法內(nèi)部對應(yīng)著不同的默認(rèn)優(yōu)先級殉了。
除了這三個方法,我們也可以自己設(shè)置優(yōu)先級的值拟枚,可以通過priority()方法來設(shè)置薪铜。
*/
[self.redViewmas_makeConstraints:^(MASConstraintMaker *make){
make.center.equalTo(self.view);
make.width.equalTo(self.view).priorityLow();
make.width.mas_equalTo(20).priorityHigh();
make.height.equalTo(self.view).priority(200);
make.height.mas_equalTo(100).priority(1000);
}];
Masonry也幫我們定義好了一些默認(rèn)的優(yōu)先級常量轧坎,分別對應(yīng)著不同的數(shù)值酷誓,優(yōu)先級最大數(shù)值是1000批狱。
staticconstMASLayoutPriorityMASLayoutPriorityRequired=UILayoutPriorityRequired;
staticconstMASLayoutPriorityMASLayoutPriorityDefaultHigh=UILayoutPriorityDefaultHigh;
staticconstMASLayoutPriorityMASLayoutPriorityDefaultMedium=500;
staticconstMASLayoutPriorityMASLayoutPriorityDefaultLow=UILayoutPriorityDefaultLow;
staticconstMASLayoutPriorityMASLayoutPriorityFittingSizeLevel=UILayoutPriorityFittingSizeLevel;
設(shè)置約束比例
// 設(shè)置當(dāng)前約束值乘以多少坎背,例如這個例子是redView的寬度是self.view寬度的0.2倍。
[self.redViewmas_makeConstraints:^(MASConstraintMaker *make){
make.center.equalTo(self.view);
make.height.mas_equalTo(30);
make.width.equalTo(self.view).multipliedBy(0.2);//寬度是self.view的1/5
}];
/**?
下面設(shè)置make.height的數(shù)組是關(guān)鍵蜒滩,通過這個數(shù)組可以設(shè)置這三個視圖高度相等滨达。其他例如寬度之類的,也是類似的方式俯艰。
*/
[self.yellowViewmas_makeConstraints:^(MASConstraintMaker *make){
make.left.right.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(0,padding,padding,padding));
make.height.equalTo(@[self.blueView,self.redView]);
}];
UITableView動態(tài)Cell高度
在iOS UI開發(fā)過程中捡遍,UITableView的動態(tài)Cell高度一直都是個問題。實現(xiàn)這樣的需求竹握,實現(xiàn)方式有很多種画株,只是實現(xiàn)起來復(fù)雜程度和性能的區(qū)別。
在不考慮性能的情況下啦辐,tableView動態(tài)Cell高度谓传,可以采取估算高度的方式。如果通過估算高度的方式實現(xiàn)的話芹关,無論是純代碼還是Interface Builder续挟,都只需要兩行代碼就可以完成Cell自動高度適配。
實現(xiàn)方式:
需要設(shè)置tableView的rowHeight屬性侥衬,這里設(shè)置為自動高度诗祸,告訴系統(tǒng)Cell的高度是不固定的,需要系統(tǒng)幫我們進(jìn)行計算浇冰。然后設(shè)置tableView的estimatedRowHeight屬性贬媒,設(shè)置一個估計的高度聋亡。(我這里用的代理方法肘习,實際上都一樣)
原理:
這樣的話,在tableView被創(chuàng)建之后坡倔,系統(tǒng)會根據(jù)estimatedRowHeight屬性設(shè)置的值漂佩,為tableView設(shè)置一個估計的值。然后在Cell顯示的時候再獲取Cell的高度罪塔,并刷新tableView的contentSize投蝉。
-(void)tableViewConstraints{
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make){
make.edges.equalTo(self.view);
}];
}
-(NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section{
return self.dataList.count;
}
-(MasonryTableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath{
MasonryTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:LXZTableViewCellIdentifier];
[cell reloadViewWithText:self.dataList[indexPath.row]];
returncell;
}
// 需要注意的是,這個代理方法和直接返回當(dāng)前Cell高度的代理方法并不一樣征堪。
// 這個代理方法會將當(dāng)前所有Cell的高度都預(yù)估出來瘩缆,而不是只計算顯示的Cell,所以這種方式對性能消耗還是很大的佃蚜。
// 所以通過設(shè)置estimatedRowHeight屬性的方式庸娱,和這種代理方法的方式着绊,最后性能消耗都是一樣的。
-(CGFloat)tableView:(UITableView *)tableViewestimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50.f;
}
-(UITableView *)tableView{
if(!_tableView){
_tableView=[[UITableView alloc]initWithFrame:CGRectZerostyle:UITableViewStylePlain];
_tableView.delegate=self;
_tableView.dataSource=self;
// 設(shè)置tableView自動高度
_tableView.rowHeight=UITableViewAutomaticDimension;
[_tableView registerClass:[MasonryTableViewCell class] forCellReuseIdentifier:LXZTableViewCellIdentifier];
[self.view addSubview:_tableView];
}
return_tableView;
}
注意: