iOS學習之自動布局

Autolayout:

最重要的兩個概念

  • 約束:對控件位置和大小的限定條件
  • 參照:對控件設置的約束是相對于哪一個視圖而言的

自動布局的核心計算公式:

obj1.property1 =(obj2.property2 * multiplier)+ constant value

解釋:obj1的property1屬性等于obj2的property2屬性乘以multiplier(系數(shù))再加constant(常量);

約束的優(yōu)先級:

約束的priority屬性表示約束的優(yōu)先級苟翻,取值區(qū)間為[0,1000],默認為1000。priority值越大遍蟋,表示優(yōu)先級越高,會優(yōu)先執(zhí)行。優(yōu)先級低的約束只有在優(yōu)先級較高的約束失效后才會執(zhí)行。

警告和錯誤:

在使用storyboard和xib設置約束時裁僧,約束有可能會變成黃色或者紅色。當發(fā)生這樣的情況時慕购,就說明設置的約束有問題聊疲。

  • 如果約束是黃色的,這只是一個警告沪悲,代表控件的frame和設置的約束不相符获洲,更新frame或者更新約束就可以解決。
  • 如果約束是紅色的殿如,這就代表錯誤贡珊,約束設置不完全或者某兩個約束有沖突最爬,只有約束設置完整并且沒有沖突,紅色錯誤提示才會消失飞崖。

添加約束的3條規(guī)則:

  • 對于兩個同層級View之間的約束關系烂叔,應該添加到它們的父View之上。
同層級的View
  • 對于兩個不同層級View之間的約束關系固歪,應該添加到它們最近的共同父View上蒜鸡。


    不同層級的View
  • 對于有層次關系的兩個view之間的約束關系,添加到層次較高的父view上
有層級關系的View

代碼實現(xiàn)Autolayout:

代碼實現(xiàn)Autolayout需要注意:

  • 必須先禁止autoresizing功能牢裳,設置View的下面屬性為NO
    view.translatesAutoresizingMaskIntoConstraints = NO;
  • 添加約束之前逢防,一定要保證相關控件都已經添加到各自的父控件上了
  • 不用再給View設置frame

利用NSLayoutConstraint類創(chuàng)建具體的約束對象

添加約束到相應的View上:

- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray *)constraints;

NSLayoutConstraint:

一個NSLayoutConstraint對象就代表一個約束,可以通過修改NSLayoutConstraint對象的屬性來修改約束蒲讯。

創(chuàng)建約束對象常用的方法:

/**
 *  添加一個約束忘朝,其實就是根據(jù)公式來計算約束
 *  obj1.property1 =(obj2.property2 * multiplier)+ constant value
 *  @param view1      需要添加約束的View
 *  @param attr1      需要添加的約束(左邊、右邊判帮、長寬還是局嘁。。晦墙。)
 *  @param relation   約束關系(大于悦昵、等于還是小于)
 *  @param view2      參照View(約束是相對于哪個View而言)
 *  @param attr2      參照View的哪一個參數(shù)(左邊、右邊晌畅、長寬還是但指。。抗楔。)
 *  @param multiplier 系數(shù)
 *  @param c          常量值
 *
 *  @return 返回一個創(chuàng)建好的約束
 */

+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

示例:

UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];

//關閉Autoresizing
blueView.translatesAutoresizingMaskIntoConstraints = NO;

//創(chuàng)建左邊約束
NSLayoutConstraint *leftLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
[self.view addConstraint:leftLc];

//創(chuàng)建右邊約束
NSLayoutConstraint *rightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
[self.view addConstraint:rightLc];

//創(chuàng)建底部約束
NSLayoutConstraint *bottomLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20];
[self.view addConstraint:bottomLc];

//創(chuàng)建高度約束
NSLayoutConstraint *heightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:50];
[blueView addConstraint: heightLc];

效果圖:


豎屏效果
橫屏效果

使用VFL語句添加約束:

使用VFL來創(chuàng)建約束數(shù)組:

/**
*  使用VFL語句來創(chuàng)建約束數(shù)組
*
*  @param format  VFL語句
*  @param opts    約束類型
*  @param metrics VFL語句中用到的具體數(shù)值
*  @param views   VFL語句中用到的控件
*
*  @return 返回創(chuàng)建好的約束數(shù)組
*/
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;

VFL語句示例:

H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton寬72棋凳,acceptButton寬50,它們之間間距12

H:[wideView(>=60@700)]
wideView寬度大于等于60point连躏,該約束條件優(yōu)先級為700(優(yōu)先級最大值為1000剩岳,優(yōu)先級越高的約束越先被滿足)

V:[redBox][yellowBox(==redBox)]
豎直方向上,先有一個redBox入热,其下方緊接一個高度等于redBox高度的yellowBox

H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上卢肃,F(xiàn)ind距離父view左邊緣默認間隔寬度,之后是FindNext距離Find間隔默認寬度才顿;再之后是寬度不小于20的FindField莫湘,它和FindNext以及父view右邊緣的間距都是默認寬度。(豎線“|” 表示superview的邊緣)

VFL代碼示例:

// 創(chuàng)建藍色View
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];

    // 創(chuàng)建紅色View
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];

    // VFL創(chuàng)建約束
    // 水平方向
    NSString *VFL_H = @"H:|-space-[blueView]-space-[redView(==blueView)]-space-|";
    NSDictionary *metrics = @{
                              @"space" : @30,
                              };
    //    NSDictionary *views = @{
    //                            @"blueView" : blueView,
    //                            @"redView" : redView
    //                            };
    NSDictionary *views = NSDictionaryOfVariableBindings(blueView,redView);

    NSArray *arrayH = [NSLayoutConstraint constraintsWithVisualFormat:VFL_H options:NSLayoutFormatAlignAllTop metrics:metrics views:views];
    [self.view addConstraints:arrayH];

    // 垂直方向
    NSString *VFL_V = @"V:[blueView(50)]-space-|";
    NSArray *arrayV = [NSLayoutConstraint constraintsWithVisualFormat:VFL_V options:kNilOptions metrics:metrics views:views];
    [self.view addConstraints:arrayV];

    // 添加紅色View的約束
    // 添加高度約束
    NSLayoutConstraint *redV_height = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
    [self.view addConstraint:redV_height];

效果圖:

豎屏效果
橫屏效果

Masonry的使用:

Masonry是目前最流行的Autolayout第三方框架郑气,讓你可以用簡單的代碼來編寫Autolayout幅垮,省去了蘋果官方繁復的Autolayout代碼,大大提升了開發(fā)效率尾组。

mas_equalToequalTo

默認情況下mas_equalTo有自動包裝功能忙芒,比如自動將20包裝為@20示弓。equalTo沒有自動包裝功能。

如果添加了下面的宏呵萨,那么mas_equalToequalTo就沒有區(qū)別:

#define MAS_SHORTHAND_GLOBALS
// 注意:這個宏一定要添加到#import "Masonry.h"前面

mas_widthwidth:

默認情況下
widthmake對象的一個屬性奏属,用來添加寬度約束用的,表示對寬度進行約束潮峦。mas_width是一個屬性值囱皿,用來當做equalTo的參數(shù),表示某個控件的寬度屬性忱嘹。

如果添加了下面的宏嘱腥,mas_width也可以寫成width:
#define MAS_SHORTHAND

mas_heightmas_centerX以此類推拘悦。

下面用Masonry框架實現(xiàn)一下上面VFL語句的示例齿兔,對比一下就會發(fā)現(xiàn)有了Masonry框架以后自動布局變得多么容易:

//創(chuàng)建藍色控件
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];

//創(chuàng)建紅色控件
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];

// 添加blueView的約束
[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(redView.width).offset(0);
    make.height.equalTo(redView.height).offset(0);
    make.height.equalTo(100);
    make.left.equalTo(blueView.superview.left).offset(20);
    make.bottom.equalTo(blueView.superview.bottom).offset(-20);
    make.right.equalTo(redView.left).offset(-20);
}];

// 添加redView的約束
[redView makeConstraints:^(MASConstraintMaker *make) {
    make.bottom.equalTo(redView.superview.bottom).offset(-20);
    make.right.equalTo(redView.superview.right).offset(-20);
}];

Masonry框架提供了很多示例程序,感興趣的可以打開上面GitHub的鏈接下載下來仔細研究础米,這里就不多寫了分苇。
GitHub鏈接為:https://github.com/SnapKit/Masonry

約束動畫:

在執(zhí)行動畫時記得調用以下方法:

//在修改了約束之后,只要執(zhí)行下面代碼屁桑,約束就能做出動畫效果
[UIView animateWithDuration:0.5 animations:^{
      [self.view layoutIfNeeded];
  }];

使用Autolayout實現(xiàn)UILabel內容包裹:

  • 1医寿、設置UILabel的位置約束
  • 2、設置label.numberOfLines = 0;,使label能夠自動換行來計算高度
  • 3掏颊、代碼創(chuàng)建約束時,應設置label的最大寬度preferredMaxLayoutWidth艾帐。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末乌叶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子柒爸,更是在濱河造成了極大的恐慌准浴,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捎稚,死亡現(xiàn)場離奇詭異乐横,居然都是意外死亡,警方通過查閱死者的電腦和手機今野,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門葡公,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人条霜,你說我怎么就攤上這事催什。” “怎么了宰睡?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵蒲凶,是天一觀的道長气筋。 經常有香客問我,道長旋圆,這世上最難降的妖魔是什么宠默? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮灵巧,結果婚禮上搀矫,老公的妹妹穿的比我還像新娘。我一直安慰自己孩等,他們只是感情好艾君,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肄方,像睡著了一般冰垄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上权她,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天虹茶,我揣著相機與錄音,去河邊找鬼隅要。 笑死蝴罪,一個胖子當著我的面吹牛,可吹牛的內容都是我干的步清。 我是一名探鬼主播要门,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼廓啊!你這毒婦竟也來了欢搜?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤谴轮,失蹤者是張志新(化名)和其女友劉穎炒瘟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體第步,經...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡疮装,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粘都。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廓推。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翩隧,靈堂內的尸體忽然破棺而出受啥,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布滚局,位于F島的核電站居暖,受9級特大地震影響,放射性物質發(fā)生泄漏藤肢。R本人自食惡果不足惜太闺,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嘁圈。 院中可真熱鬧省骂,春花似錦、人聲如沸最住。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涨缚。三九已至轧粟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脓魏,已是汗流浹背兰吟。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留茂翔,地道東北人混蔼。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像珊燎,于是被迫代替她去往敵國和親惭嚣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容