iOS开发之Masonry框架-使用方法须知
目錄
- 常用的屬性與常量
- Masonry使用注意
- 約束的優(yōu)先級
- Masonry添加約束的方法
- 修改約束
- 在哪創(chuàng)建我的約束
- 創(chuàng)建約束技巧:
Masonry是一個(gè)輕量級的布局框架,它擁有自己的描述語法(采用更優(yōu)雅的鏈?zhǔn)秸Z法封裝)來自動布局,具有很好可讀性且同時(shí)支持iOS和Max OS X等。
總之,對于側(cè)重寫代碼的coder,請你慢慢忘記Frame,喜歡Masonry吧
常用的屬性與常量
MASViewAttribute 以對應(yīng)的系統(tǒng)類型
| view.mas_left | NSLayoutAttributeLeft |
| view.mas_right | NSLayoutAttributeRight |
| view.mas_top | NSLayoutAttributeTop |
| view.mas_bottom | NSLayoutAttributeBottom |
| view.mas_leading | NSLayoutAttributeLeading |
| view.mas_trailing | NSLayoutAttributeTrailing |
| view.mas_width | NSLayoutAttributeWidth |
| view.mas_height | NSLayoutAttributeHeight |
| view.mas_centerX | NSLayoutAttributeCenterX |
| view.mas_centerY | NSLayoutAttributeCenterY |
| view.mas_baseline | NSLayoutAttributeBaseline |
UIView
先來一波最為常用的使用方法,大家可以看一下大致語法,下面會細(xì)講使用
//分別設(shè)置各個(gè)相對邊距(superview為view的父類視圖,下同) make.left.mas_equalTo(superView.mas_left).mas_offset(10); make.right.mas_equalTo(superView.mas_right).mas_offset(-10); make.top.mas_equalTo(superView.mas_top).mas_offset(10); make.bottom.mas_equalTo(superView.mas_bottom).offset(-10);//直接連接使用left大于等于某個(gè)值 make.left.mas_greaterThanOrEqualTo(10);//設(shè)置寬和高 make.width.mas_equalTo(60); make.height.mas_equalTo(60);//.設(shè)置center和寬高比 make.center.mas_equalTo(superView); make.width.mas_equalTo(superView).multipliedBy(1.00/3); make.height.mas_equalTo(superView).multipliedBy(0.25);//.關(guān)于約束優(yōu)先級,此處要注意約束沖突的問題,統(tǒng)一約束優(yōu)先級大的生效 make.left.mas_equalTo(100); make.left.mas_equalTo(view.superview.mas_left).offset(10); make.left.mas_equalTo(20).priority(700); make.left.mas_equalTo(40).priorityHigh(); make.left.mas_equalTo(60).priorityMedium(); make.left.mas_equalTo(80).priorityLow();//如果你想讓view的(x坐標(biāo))左邊大于等于label的左邊,以下兩個(gè)約束的寫法效果一樣 make.left.greaterThanOrEqualTo(label); make.left.greaterThanOrEqualTo(label.mas_left);注:約束的鏈?zhǔn)綄懛ㄖ?#xff0c;不包含其他相對的view時(shí),默認(rèn)為其superview,即make.left.mas_equalTo(100);等價(jià)于make.left.mas_equalTo(view.superview.mas_left).offset(10);和make.left.mas_equalTo(view.superview).offset(10);
更加便利的約束方法
Masonry提供了一些便利的方法供我們同時(shí)創(chuàng)建多個(gè)不同的約束,他們被稱為MASCompositeConstraints,如:
edges:
// 使一個(gè)view的top, left, bottom, right 等于view2的 make.edges.equalTo(view2);//相對于superviewde上左下右邊距分別為5,10,15,20 make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))size:
// 使得寬度和高度大于等于 titleLabel make.size.greaterThanOrEqualTo(titleLabel)// 相對于superview寬度大100,高度小50 make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))center:
//中心與button1對齊 make.center.equalTo(button1)//水平方向中心相對向左偏移5,豎直方向中心向下偏移10 make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))你可以在約束鏈里添加相應(yīng)的view來增加代碼的可讀性:
// 除了top,所有的邊界與superview對齊 make.left.right.and.bottom.equalTo(superview);make.top.equalTo(otherView);NSNumber
自動布局允許使用常量去設(shè)置寬或高,如果你想通過一個(gè)數(shù)字設(shè)置一個(gè)view的最小和最大的width,可以用equality blocks,如下:
//width >= 200 && width <= 400make.width.greaterThanOrEqualTo(@200);make.width.lessThanOrEqualTo(@400)然而自動布局不允許對齊屬性的約束(如:left,right,centerY等)設(shè)置為常量值,你可以使用NSNumber來設(shè)置相對于父類view這些約束屬性,如:
// creates view.left = view.superview.left + 10 make.left.lessThanOrEqualTo(@10)如果你不想使用NSNumber來設(shè)置,也可以用如下結(jié)構(gòu)來創(chuàng)建你的約束,如:
make.top.mas_equalTo(42);make.height.mas_equalTo(20);make.size.mas_equalTo(CGSizeMake(50, 100));make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));NSArray
用數(shù)組添加集中不同類的約束,如:
常見約束的各種類型
/**1.尺寸:width、height、size2.邊界:left、leading、right、trailing、top、bottom3.中心點(diǎn):center、centerX、centerY4.邊界:edges5.偏移量:offset、insets、sizeOffset、centerOffset6.priority()約束優(yōu)先級(0~1000),multipler乘因數(shù), dividedBy除因數(shù)*/Masonry使用注意
mas_equalTo和equalTo的區(qū)別:
- equalTo:僅支持基本類型;
- mas_equalTo:支持類型轉(zhuǎn)換,支持復(fù)雜類型。是對equalTo的封裝。支持CGSize CGPoint NSNumber UIEdgeinsets。
以下實(shí)現(xiàn)的是相同的效果:make.width.equalTo(@100);跟make.width.mas_equalTo(100);
- mas_equalTo是一個(gè)Macro,比較 值;
- equalTo比較View。
以下實(shí)現(xiàn)的是相同的效果make.bottom.mas_equalTo(ws.view.mas_bottom);跟make.bottom.equalTo(ws.view);
mas_equalTo比equalTo多了類型轉(zhuǎn)換操作,大多數(shù)時(shí)候兩個(gè)方法是 通用的。但是
- 對于數(shù)值元素使用mas_equalTo;
- 對于對象或多個(gè)屬性的處理,使用equalTo;(特別的多個(gè)屬性時(shí),必須使用equalTo,例如make.left.and.right.equalTo(self.view))
去掉mas_前綴,只用equalTo,只需要把下面代碼添加到.prefix文件:
// 只要添加了這個(gè)宏,就不用帶mas_前綴(`equalTo`就等價(jià)于`mas_equalTo`) #define MAS_SHORTHAND// 對于默認(rèn)的約束參數(shù)自動裝箱 #define MAS_SHORTHAND_GLOBALS// 這個(gè)頭文件,一定要放在上面兩個(gè)宏的后面 #import "Masonry.h"注意點(diǎn)方法with和and,這兩個(gè)方法其實(shí)沒有做任何操作,方法只是返回對象本身,這個(gè)方法的作用,完全是為了可讀性。
make.left.and.right.equalTo(self.view);和make.left.right.equalTo(self.view);是完全一樣的,但是加了and方法的語法,可讀性更好。
multipliedBy的使用只能是設(shè)置同一個(gè)控件的,比如這里的bottomInnerView,make.height.mas_equalTo(bottomInnerView.mas_width).multipliedBy(3);
簡化:
[iconView makeConstraints:^(MASConstraintMaker *make){ make.top.equalTo(self.view).with.offset(30); make.left.equalTo(self.view).with.offset(30); make.bottom.equalTo(self.view).with.offset(-30); make.right.equalTo(self.view).with.offset(-30); }]可以簡化為
make.top.left.bottom.and.right.equalTo(self.view).with.insets(UIEdgeInsetsMake(10,10,10,10));
或
make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(30.30.30.30));
其中l(wèi)eading與left trailing與right在正常情況下是等價(jià)的,但是在一些布局是從右至左時(shí)(比如阿拉伯文),則會對調(diào),所以基本可以不理不用。用left和right就好。用leading或trailing后就不要用left或right,如果混用會出現(xiàn)崩潰。
對label的約束比必須設(shè)置最大的約束寬度;
self.titleLabel.preferredMaxLayoutWidth = w - 100;
因?yàn)閕OS中原點(diǎn)在左上角所以注意使用offset時(shí)注意right和bottom用負(fù)數(shù)
使用Masonry不需要設(shè)置控件的translatesAutoresizingMaskIntoConstraints屬性為NO,(錯(cuò)誤觀點(diǎn):為防止block中的循環(huán)引用,使用弱引用),因?yàn)樵谶@里block是局部的引用,block內(nèi)部引用self不會造成循環(huán)應(yīng)用的。(沒必要的寫法:__weak typeof (self) weakSelf = self;)
Masonry約束控件出現(xiàn)沖突的問題:當(dāng)約束沖突發(fā)生的時(shí)候,我們可以設(shè)置view的key來定位是哪個(gè)view。
比如:
如果覺得這樣一個(gè)個(gè)設(shè)置比較繁瑣,Masonry提供了批量設(shè)置的宏:
// 一句代碼即可全部設(shè)置 MASAttachKeysMASAttachKeys(redView,greenView,blueView);約束的優(yōu)先級
- priorityHigh等價(jià)于UILayoutPriorityDefaultHigh,優(yōu)先級值為750。
- priorityMedium介于高優(yōu)先級和低優(yōu)先級之間,優(yōu)先級值在250~750之間。
- priorityLow等價(jià)于UILayoutPriorityDefaultLow,優(yōu)先級值為250。
優(yōu)先級可以在約束的尾部添加:
make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow(); make.top.equalTo(label.mas_top).with.priority(600);Greater/Less一般與Priority一起使用,為一個(gè)Constraint設(shè)置了Greater/Less后,調(diào)整Priority。如果Constraint的Priority的值越大,程序優(yōu)先設(shè)置它的Constraint效果。
Masonry添加約束的方法
這個(gè)方法只會添加新的約束:
[view makeConstraints:^(MASConstraintMaker *make) {}];這個(gè)方法將會覆蓋以前的某些特定的約束
[view updateConstraints:^(MASConstraintMaker *make) {}];這個(gè)方法會將以前的所有約束刪掉,添加新的約束
```[view remakeConstraints:^(MASConstraintMaker *make) {}];```- 里面覺得最好用的是masonry_remakeConstraints,保證不會錯(cuò),
要記得將約束寫在updateConstraints里面:
- (void) updateConstraints{}然后調(diào)用下面這一串:
[self setNeedsUpdateConstraints];[self updateConstraintsIfNeeded];[self layoutIfNeeded];否則不會更新。
setNeedsLayout:
- setNeedsLayout:告知頁面需要刷新,但是不會立刻開始更新。執(zhí)行后會立刻調(diào)用layoutSubviews。
- layoutIfNeed:告知頁面布局立刻更新。所以一般都會和setNeedsLayout一起使用。如果希望立刻生成新的frame需要調(diào)用此方法。利用這點(diǎn):一般布局動畫可以在更新布局后直接使用這個(gè)方法讓動畫生效。
- layoutSubViews:系統(tǒng)重寫布局setNeedsUpdateConstraints:告訴需要更新約束,但是不會立刻開始。
- updateConstraintsIfNeeded:告知立刻更新約束。
- updateConstraints:系統(tǒng)更新約束。
修改約束
有時(shí)候,你為了實(shí)現(xiàn)動畫或者移除替換一些約束時(shí),你需要去修改一些已經(jīng)存在的約束,Masonry提供了一些不同的方法去更新約束,你也可以將多個(gè)約束存在數(shù)組里。
References
你可以持有某個(gè)特定的約束,讓其成為成員變量或者屬性
//設(shè)置為公共或私接口
@property (nonatomic, strong) MASConstraint *topConstraint;...// 添加約束[view1 mas_makeConstraints:^(MASConstraintMaker *make) {self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);make.left.equalTo(superview.mas_left).with.offset(padding.left);}];...// 然后可以調(diào)用 //該約束移除 [self.topConstraint uninstall]; //重新設(shè)置value,最常用 self.topConstraint.mas_equalTo(20); //該約束失效 [self.topConstraint deactivate]; //該約束生效 [self.topConstraint activate];mas_updateConstraints
如果你只是想更新一下view對應(yīng)的約束,可以使用 mas_updateConstraints 方法代替 mas_makeConstraints方法
//這是蘋果推薦的添加或者更新約束的地方
// 在響應(yīng)setNeedsUpdateConstraints方法時(shí),這個(gè)方法會被調(diào)用多次
// 此方法會被UIKit內(nèi)部調(diào)用,或者在你觸發(fā)約束更新時(shí)調(diào)用
- (void)updateConstraints {[self.growingButton mas_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);}];//調(diào)用super [super updateConstraints];}mas_remakeConstraints
mas_updateConstraints只是去更新一些約束,然而有些時(shí)候修改一些約束值是沒用的,這時(shí)候mas_remakeConstraints就可以派上用場了
mas_remakeConstraints某些程度相似于mas_updateConstraints,但不同于mas_updateConstraints去更新約束值,他會移除之前的view的所有約束,然后再去添加約束
- (void)changeButtonPosition {[self.button mas_remakeConstraints:^(MASConstraintMaker *make) {make.size.equalTo(self.buttonSize);if (topLeft) {make.top.and.left.offset(10);} else {make.bottom.and.right.offset(-10); }}];蘋果官方建議:添加/更新約束在updateConstraints這個(gè)方法內(nèi)
// this is Apple's recommended place for adding/updating constraints - (void)updateConstraints { //更新約束 [self.btn 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); }];//according to apple super should be called at end of method //最后必須調(diào)用父類的更新約束 [super updateConstraints]; }
在哪創(chuàng)建我的約束
貼一個(gè)官方說明的例子:
@implementation DIYCustomView- (id)init {self = [super init];if (!self) return nil;// --- Create your views here ---self.button = [[UIButton alloc] init];return self;}// tell UIKit that you are using AutoLayout+ (BOOL)requiresConstraintBasedLayout {return YES;}// this is Apple's recommended place for adding/updating constraints- (void)updateConstraints {// --- remake/update constraints here[self.button remakeConstraints:^(MASConstraintMaker *make) {make.width.equalTo(@(self.buttonSize.width));make.height.equalTo(@(self.buttonSize.height));}];//according to apple super should be called at end of method[super updateConstraints];}- (void)didTapButton:(UIButton *)button {// --- Do your changes ie change variables that affect your layout etc ---self.buttonSize = CGSize(200, 200);// tell constraints they need updating[self setNeedsUpdateConstraints];}創(chuàng)建約束技巧:
多個(gè)(2個(gè)以上)控件的等間隔排序顯示
/** * axisType 軸線方向 * fixedSpacing 間隔大小 * fixedItemLength 每個(gè)控件的固定長度/寬度 * leadSpacing 頭部間隔 * tailSpacing 尾部間隔 * *///1. 等間隔排列 - 多個(gè)控件間隔固定,控件長度/寬度變化 - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;//2. 等間隔排列 - 多個(gè)固定大小固定,間隔空隙變化 - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;多行l(wèi)abel的約束問題
//創(chuàng)建labelself.label = [UILabel new];self.label.numberOfLines = 0;self.label.lineBreakMode = NSLineBreakByTruncatingTail;self.label.text = @"有的人,沒事時(shí)喜歡在朋友圈里到處點(diǎn)贊,東評論一句西評論一句,比誰都有存在感。等你有事找他了,他就立刻變得很忙,讓你再也找不著。真正的朋友,平常很少聯(lián)系。可一旦你遇上了難處,他會立刻回復(fù)你的消息,第一時(shí)間站出來幫你。所謂的存在感,不是你有沒有出現(xiàn),而是你的出現(xiàn)有沒有價(jià)值。存在感,不是刷出來的,也不是說出來的。有存在感,未必是要個(gè)性鋒芒畢露、甚至鋒利扎人。翩翩君子,溫潤如玉,真正有存在感的人,反而不會刻意去強(qiáng)調(diào)他的存在感。他的出現(xiàn),永遠(yuǎn)都恰到好處。我所欣賞的存在感,不是長袖善舞巧言令色,而是對他人的真心關(guān)照;不是鋒芒畢露計(jì)較勝負(fù),而是讓人相處得舒服;不是時(shí)時(shí)刻刻聒噪不休,而是關(guān)鍵時(shí)刻能挺身而出。別總急著出風(fēng)頭,希望你能有恰到好處的存在感。";[self addSubview: self.label];[self.label makeConstraints:^(MASConstraintMaker *make) {make.left.top.equalTo(10);make.right.equalTo(-10);}];//添加約束 - (void)layoutSubviews {//1. 執(zhí)行 [super layoutSubviews];[super layoutSubviews];//2. 設(shè)置preferredMaxLayoutWidth: 多行l(wèi)abel約束的完美解決self.label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;//3. 設(shè)置preferredLayoutWidth后,需要再次執(zhí)行 [super layoutSubviews]; //其實(shí)在實(shí)際中這步不寫,也不會出錯(cuò),官方解釋是說設(shè)置preferredLayoutWidth后需要重新計(jì)算并布局界面,所以這步最好執(zhí)行[super layoutSubviews]; }UIScrollView的問題
原理同自動布局一樣 UIScrollView上添加UIView
UIView上添加需要顯示的控件 UIScrollView滾動高度取決于顯示控件的總高度
對子控件做好約束,可達(dá)到控制UIView的大小
轉(zhuǎn)載于:https://www.cnblogs.com/cy521/p/10266481.html
總結(jié)
以上是生活随笔為你收集整理的iOS开发之Masonry框架-使用方法须知的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P4336 [SHOI2016]黑暗前的
- 下一篇: poping 心法