iOS開發(fā)之 Autolayout 詳解

iOS開發(fā)之 Autolayout 詳解

2018-05-24-1_HemKn1OC2bh7tUpK7_p0Ng

1. 概述

  1. Autolayout 是 Apple 自 iOS6 開始引入的旨在解決不同屏幕之間布局適配的技術(shù)
  2. 蘋果官方推薦開發(fā)者使用 Autolayout 進(jìn)行UI界面的布局
  3. Autolayout 有兩個(gè)核心概念:1. 參照揣炕。 2. 約束
  4. 使用Autolayout的注意點(diǎn):
    1. 添加約束之前需要保證控件已被添加到父控件中
    2. 不需要再給View設(shè)置frame
    3. 禁止 autoresizing 功能唱较。

2. 代碼實(shí)現(xiàn) Autolayout

2.1 步驟:

  1. 把 View 添加到父控件上含潘。

  2. 添加約束到相應(yīng)的 View 上反璃。

    - (void)addConstraint:(NSLayoutConstraint *)constraint;
    - (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints;
    
  3. 自動(dòng)布局核心公式:
    obj1.property1 =(obj2.property2 * multiplier)+ constant value

NSLayoutConstraint
/**
view1 :要約束的控件
attr1 :約束的類型(做怎樣的約束)
relation :與參照控件之間的關(guān)系
view2 :參照的控件
attr2 :約束的類型(做怎樣的約束)
multiplier :乘數(shù)
c :常量
*/
+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

2.2 實(shí)例

添加一個(gè)左間距100 上間距200丧失,寬150 高64 的紅視圖:
- (void)testAutolayout1 {
    UIView *redV = [[UIView alloc] init];
    redV.backgroundColor = [UIColor redColor];
    redV.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redV];
    /**
     view1 :要約束的控件
     attr1 :約束的類型(做怎樣的約束)
     relation :與參照控件之間的關(guān)系
     view2 :參照的控件
     attr2 :約束的類型(做怎樣的約束)
     multiplier :乘數(shù)
     c :常量
     */
    /// 左間距100:
    NSLayoutConstraint *consLeft = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:100];
    [self.view addConstraint:consLeft];
    
    /// 上間距200:
    NSLayoutConstraint *consTop = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:200];
    [self.view addConstraint:consTop];
    
    /// 寬150:
    NSLayoutConstraint *consWidth = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:150];
    [redV addConstraint:consWidth];
    
    /// 高64:
    NSLayoutConstraint *consHeight = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:64];
    [redV addConstraint:consHeight];
}
在上視圖基礎(chǔ)上添加一個(gè)與紅視圖右間距相同恕汇,高度相同阀坏,頂部距離紅色視圖間距20肤视,寬度為紅色視圖一半的藍(lán)色View
 UIView *blueV = [[UIView alloc] init];
    blueV.backgroundColor = [UIColor blueColor];
    blueV.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueV];
    
    /// 和 redV 右間距為0
    NSLayoutConstraint *b_consRight = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0];
    [self.view addConstraint:b_consRight];
    
    /// 和 redV 等高
    NSLayoutConstraint *b_consHeight = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0];
    [self.view addConstraint:b_consHeight];
    
    /// 寬度是 redV 的一半
    NSLayoutConstraint *b_consWidth = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];
    [self.view addConstraint:b_consWidth];
    
    /// 頂部距離 redV 20
    NSLayoutConstraint *b_consTop = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20.0];
    [self.view addConstraint:b_consTop];

最終效果:


屏幕快照 2018-05-24 下午3.46.26

2.3 添加約束的規(guī)則

在創(chuàng)建約束之后橄教,需要將其添加到作用的view上橙依。
在添加時(shí)要注意目標(biāo)view需要遵循以下規(guī)則:

(1)對(duì)于兩個(gè)同層級(jí)view之間的約束關(guān)系,添加到它們的父view上
(2)對(duì)于兩個(gè)不同層級(jí)view之間的約束關(guān)系拴曲,添加到他們最近的共同父view上
(3)對(duì)于有層次關(guān)系的兩個(gè)view之間的約束關(guān)系,添加到層次較高的父view上

3. VFL

VFL全稱是Visual Format Language凛忿,翻譯過來是“可視化格式語言”澈灼,是蘋果公司為了簡化Autolayout的編碼而推出的抽象語言。

    /*
     format :VFL語句
     opts :約束類型
     metrics :VFL語句中用到的具體數(shù)值
     views :VFL語句中用到的控件
     */
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *,id> *)views;

@{@"redV" : redV} 等價(jià)于 NSDictionaryOfVariableBindings(redV)

NSDictionary *views =

NSDictionaryOfVariableBindings(blueView, redView);

NSArray *conts2 =

[NSLayoutConstraint constraintsWithVisualFormat:

@"V:[blueView(==blueHeight)]-margin-|" options:0 metrics:

@{@"blueHeight" : @40, @"margin" : @20} views:views];

約束格式說明:

水平方向        H:
垂直方向        V:
Views         [view]
SuperView      |
關(guān)系         >=,==,<=
空間,間隙       -
優(yōu)先級(jí)        @value

3.1 VFL 部分語法:

H:|-100-[redV(200)]-|

水平方向距離左邊距100店溢,寬度200

V:|-200-[redV(64)]-|

垂直方向距離頂部200叁熔,高度64

H:[redV(72)]-12-[blueV(50)]

水平方向redV 寬度72,blueV 寬度50床牧,他們之間間距12

H:[redV(>=60@700)]

水平方向redV寬度大于等于60荣回,優(yōu)先級(jí)為700 (優(yōu)先級(jí)最大1000)

V:[redBox]-[yellowBox(==redBox)]

豎直方向上,先有一個(gè)redBox叠赦,其下方緊接一個(gè)高度等于redBox高度的yellowBox

H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|

水平方向上驹马,F(xiàn)ind距離父view左邊緣默認(rèn)間隔寬度,之后是FindNext距離Find間隔默認(rèn)寬度除秀;再之后是寬度不小于20的FindField糯累,它和FindNext以及父view右邊緣的間距都是默認(rèn)寬度。(豎線“|” 表示superview的邊緣)

3.2 VFL的語法

  • 標(biāo)準(zhǔn)間隔:[button]-[textField]
  • 寬約束:[button(>=50)]
  • 與父視圖的關(guān)系:|-50-[purpleBox]-50-|
  • 垂直布局:V:[topField]-10-[bottomField]
  • Flush Views:[maroonView][buleView]
  • 權(quán)重:[button(100@20)]
  • 等寬:[button(==button2)]
  • Multiple Predicates:[flexibleButton(>=70,<=100)]

注意事項(xiàng)

創(chuàng)建這種字符串時(shí)需要注意一下幾點(diǎn):

  • H:和V:每次都使用一個(gè)册踩。
  • 視圖變量名出現(xiàn)在方括號(hào)中泳姐,例如[view]。
  • 字符串中順序是按照從頂?shù)降自菁瑥淖蟮接?/li>
  • 視圖間隔以數(shù)字常量出現(xiàn)胖秒,例如-10-。
  • |表示父視圖

3.3 使用Auto Layout時(shí)需要注意的點(diǎn)

  • 注意禁用Autoresizing Masks慕的。對(duì)于每個(gè)需要使用Auto Layout的視圖需要調(diào)用setTranslatesAutoresizingMaskIntoConstraints:NO
  • VFL語句里不能包含空格和>阎肝,<這樣的約束
  • 布局原理是由外向里布局,最先屏幕尺寸肮街,再一層一層往里決定各個(gè)元素大小风题。
  • 刪除視圖時(shí)直接使用removeConstraint和removeConstraints時(shí)需要注意這樣刪除是沒法刪除視圖不支持的約束導(dǎo)致view中還包含著那個(gè)約束(使用第三方庫時(shí)需要特別注意下)。解決這個(gè)的辦法就是添加約束時(shí)用一個(gè)局部變量保存下,刪除時(shí)進(jìn)行比較刪掉和先前那個(gè)沛硅,還有個(gè)辦法就是設(shè)置標(biāo)記眼刃,constraint.identifier = @“What you want to call”。

3.4 布局約束規(guī)則

表達(dá)布局約束的規(guī)則可以使用一些簡單的數(shù)學(xué)術(shù)語摇肌,如下表

類型 描述
屬性 視圖位置 NSLayoutAttributeLeft, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom
屬性 視圖前面后面 NSLayoutAttributeLeading, NSLayoutAttributeTrailing
屬性 視圖的寬度和高度 NSLayoutAttributeWidth, NSLayoutAttributeHeight
屬性 視圖中心 NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
屬性 視圖的基線擂红,在視圖底部上方放置文字的地方 NSLayoutAttributeBaseline
屬性 占位符,在與另一個(gè)約束的關(guān)系中沒有用到某個(gè)屬性時(shí)可以使用占位符 NSLayoutAttributeNotAnAttribute
關(guān)系 允許將屬性通過等式和不等式相互關(guān)聯(lián) NSLayoutRelationLessThanOrEqual, NSLayoutRelationEqual, NSLayoutRelationGreaterThanOrEqual
數(shù)學(xué)運(yùn)算 每個(gè)約束的乘數(shù)和相加性常數(shù) CGFloat值

3.5 View的改變會(huì)調(diào)用哪些方法

  • 改變frame.origin不會(huì)掉用layoutSubviews
  • 改變frame.size會(huì)使 superVIew的layoutSubviews調(diào)用和自己view的layoutSubviews方法
  • 改變bounds.origin和bounds.size都會(huì)調(diào)用superView和自己view的layoutSubviews方法

3.6 VFL 實(shí)例:

- (void)testVFL {
    UIView *redV = [[UIView alloc] init];
    redV.backgroundColor = [UIColor redColor];
    redV.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redV];
    
    UIView *blueV = [[UIView alloc] init];
    blueV.backgroundColor = [UIColor blueColor];
    blueV.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueV];
    /*
     format :VFL語句
     opts :約束類型
     metrics :VFL語句中用到的具體數(shù)值
     views :VFL語句中用到的控件
     */
    //水平方向 redV 左右間距為20
    NSArray *cons1 = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[redV]-20-|" options:0 metrics:nil views:@{@"redV":redV}];
    [self.view addConstraints:cons1];
    
    //垂直方法redV距離頂部 100, redV 高度為64, blueV頂部距離redV 100 像素, blueV的高度等于redV
    NSArray *cons2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-margin-[redV(64)]-margin-[blueV(==redV)]" options:NSLayoutFormatAlignAllRight metrics:@{@"margin" : @100} views:NSDictionaryOfVariableBindings(redV,blueV)];
    [self.view addConstraints:cons2];
    
    NSLayoutConstraint *cons = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];
    [self.view addConstraint:cons];
}

運(yùn)行結(jié)果:


2018-05-24_3.46.26

文中演示Demo 均已開源在 GitHub上围小,這是鏈接: XWAutolayoutDemo In Github

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末昵骤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吩抓,更是在濱河造成了極大的恐慌涉茧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疹娶,死亡現(xiàn)場(chǎng)離奇詭異伴栓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)雨饺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門钳垮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人额港,你說我怎么就攤上這事饺窿。” “怎么了移斩?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵肚医,是天一觀的道長。 經(jīng)常有香客問我向瓷,道長肠套,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任猖任,我火速辦了婚禮你稚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朱躺。我一直安慰自己刁赖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布长搀。 她就那樣靜靜地躺著宇弛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪源请。 梳的紋絲不亂的頭發(fā)上枪芒,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天轿钠,我揣著相機(jī)與錄音,去河邊找鬼病苗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛症汹,可吹牛的內(nèi)容都是我干的硫朦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼背镇,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼咬展!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瞒斩,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤破婆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胸囱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祷舀,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年烹笔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裳扯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谤职,死狀恐怖饰豺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情允蜈,我是刑警寧澤冤吨,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站饶套,受9級(jí)特大地震影響漩蟆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凤跑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一爆安、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仔引,春花似錦扔仓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至儿倒,卻和暖如春版保,著一層夾襖步出監(jiān)牢的瞬間呜笑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工彻犁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叫胁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓汞幢,卻偏偏與公主長得像驼鹅,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子森篷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容