IOS SizeClass 和 Autolayout 適配各種設(shè)備

SizeClass Autolayout 在Storyboard或XB上的適配

現(xiàn)在蘋果生態(tài)圈中的設(shè)備尺寸也已經(jīng)變得種類繁多了,設(shè)備種類如下:
iPad:iPad1,iPad2,newPad,iPad4,iPad air,iPad air2,iPad mini1,iPad mini2,iPad mini3,iPad pro;
iPhone:iPhone3Gs,iPhone4,iPhone4S,iPhone5,iPhone5S,iPhone5C iPhone6,iPhone6 Plus,iPhone6S,ipad iPhone6S Plus;
iWatch

屏幕大小

  1. iPhone:3.5,4.0,4.7,5.5
  2. iPad: 7.9,9.7,12.9
  3. iWatch:1.6,1.8

想必蘋果也意識(shí)到這一點(diǎn)。都知道蘋果是以化繁為簡(jiǎn)的設(shè)計(jì)哲學(xué)深入人心的,這次再一次證明了。SizeClass是對(duì)設(shè)備尺寸的一個(gè)抽象概念,現(xiàn)在任何設(shè)備的 長、寬 被簡(jiǎn)潔地分為三種情況:普通 (Regular)緊密 (Compact)任意(Any) ,這樣,根據(jù)長和寬不同的搭配就能產(chǎn)生 3 * 3 = 9 種不同尺寸。下圖展示個(gè)每種情況對(duì)應(yīng)的設(shè)備。

autolayout.png

以前為不同的iOS設(shè)備尺寸或者同尺寸橫豎屏不同適配UI,都要根據(jù)實(shí)際情況而去計(jì)算frame。使用Size Classes是根據(jù)當(dāng)前的屏幕size類型而使用Auto Layout方式進(jìn)行布局了,要摒棄之前計(jì)算frame的思路,而改用相對(duì)布局的思維去思考(實(shí)際上還是要計(jì)算frame).

而且Xcode6最大的突破也是這里,不在需要建立不同尺寸的storyboard了,只要建立一個(gè),然后修改其view的size就可以做各種屏幕尺寸的適配,如下:

例如我要做iPad頁面設(shè)計(jì),就設(shè)置成w (Regular)/h(Regular)

然后同樣的工程,又要兼容橫屏的iPhone6 plus,就可以把view的size class設(shè)置成:w (Regular)/h(Compact),然后繼續(xù)適配


然后當(dāng)程序跑在不同的設(shè)備上,或者設(shè)備橫屏和豎屏切換,就能顯示相應(yīng)的UI了。

示例:

適配iPhone6,在RootViewController的view上添加一個(gè)新的view,讓這個(gè)新的view無論屏幕橫屏還是豎屏?xí)r候都距離其superview的邊緣50點(diǎn)寬,并且橫屏?xí)r候?yàn)榫G顏色,豎屏?xí)r候?yàn)榧t顏色。

操作如下:

  1. 切換size class為wCompact/hRegular模式


并且添加一個(gè)view,不用管其frame,并設(shè)置其背景色為紅色

接下來選中紅色的view,然后點(diǎn)擊Xcode頂部工具欄的Editor-Pin,然后分別添加紅色view相對(duì)superview邊框的約束(上下左右

添加約束的過程中會(huì)看到約束的線是黃顏色,表明當(dāng)前的約束還不能確定view的frame,需要繼續(xù)添加,當(dāng)添加完4個(gè)約束后,約束線的顏色是藍(lán)色的,表明當(dāng)前約束是正確的。

然后選中約束,設(shè)定約束的值(我們不是想讓新的view距離其superview邊界50點(diǎn)寬嗎!),4個(gè)約束都要設(shè)置。

設(shè)置完后點(diǎn)擊下view會(huì)自動(dòng)更新frame,應(yīng)該是這樣的:


2.切換size class為wRegular/hCompact模式,然后重復(fù)第一步中的設(shè)置,區(qū)別是新添加的view背景顏色設(shè)置為綠色。


示例2:

基于iPhone適配界面,添加三個(gè)view到rootView上,然后無論橫屏還是豎屏,新添加的三個(gè)view之間及與屏幕邊框的距離都保持不變的間距20點(diǎn)寬,效果如圖:

因?yàn)橐m配iPhone橫豎屏,所以修改size class為wCompact/hRegular來適配豎屏:拖拽3個(gè)view到rootView上,并設(shè)置其背景顏色


為了滿足設(shè)計(jì)要求,要添加如下constraint:

  1. 設(shè)定綠色view距離superview左邊距和上邊距;
  2. 設(shè)定黃色view距離superview右邊距和上邊距,相對(duì)綠色view的的左邊距;
  3. 設(shè)定藍(lán)色view的左邊距和右邊距和下邊距,上邊距離綠色view下邊的距離;
  4. 設(shè)定綠色view與黃色view等寬高
  5. 設(shè)定藍(lán)色view與綠色view等高

操作如下:

選中綠色view,Eidtor->Pin->Leading Space to Superview給綠色view添加相對(duì)其superview的左邊距,然后選中constraint,修改約束的值為20,其他constraint以此類推



添加完如圖:



其中紅色框部分清晰的表達(dá)了所添加的constraint;藍(lán)色框部分時(shí)添加的constraint,目前為黃色線,表明當(dāng)前的constraint還不能定位view,當(dāng)一個(gè)view的constraint正確的時(shí)候,constraint的顏色會(huì)變?yōu)樗{(lán)色。綠色線框的部分表達(dá)了constraint的數(shù)值,我們想讓邊距為20,所以設(shè)置數(shù)值為20 。wC hR Installed表明當(dāng)前constraint適用于wC hR這種size class,不適合any any的size class。

添加綠色view與黃色view之前的距離時(shí)候,由于是設(shè)定兩個(gè)子view的constraint,所以要選中兩個(gè)view,然后Editor->Pin ->Horizontal,設(shè)定值為20:


同樣方法Editor->Pin ->Width Equally,設(shè)定綠色view與黃色view等寬度,藍(lán)色view與綠色view等高,結(jié)果如圖:



但發(fā)現(xiàn)constraint顏色仍然后黃色,原因是當(dāng)前view的位置和constraint希望的不一致,更新下frame(要選中3個(gè)view,因?yàn)閏onstraint關(guān)聯(lián)3個(gè)view)或者點(diǎn)擊Document Outline中的黃色小箭頭,然后會(huì)看到具體的constraint信息來一步步調(diào)試,這個(gè)也是Xcode6最有突破的地方:


然后效果如圖:


然后運(yùn)行下項(xiàng)目吧,發(fā)現(xiàn)確實(shí)和預(yù)期的一樣。然后旋轉(zhuǎn)屏幕,是不是發(fā)現(xiàn)橫屏?xí)r候白了,屏幕什么都沒有了?原因是我們僅僅適配的豎屏,橫屏還沒有適配啊!

修改size class,iPhone4s橫屏的size class為wCompact/hCompact,而iPhone6 plus為wReguage/hCompact,那我們不如設(shè)置為wAny/hCompact吧!然后安裝上邊適配豎屏的方式適配橫屏。適配好后再次運(yùn)行,橫豎屏都應(yīng)該是我們想要的了。

小小技巧:
查看不同設(shè)備適配情況

Autolayout 純代碼的適配

在 ios6 之前沒有AutoLayout布局UI,我們布局UI是基于固定的frame,bound對(duì)控件的布局,設(shè)置控件的 位置(x,y), 尺寸(width,height)就可以把控件放在相應(yīng)的位置。

出現(xiàn)Autolayout后,我們用AutoLayout布局控件就要把之前固定設(shè)置frame、bound忘記;要想布局顯示一個(gè)控件,Autolayout以兩個(gè)詞:約束參照 動(dòng)態(tài)設(shè)置一個(gè)控件兩個(gè)東西,位置尺寸;

小結(jié):
1. 添加約束不宜過多,當(dāng)添加的約束足以表達(dá)該控件的位置與尺寸,就足夠了
2. 約束就是對(duì)控件的大小或者位置進(jìn)行約束,參照就是以某個(gè)控件的位置進(jìn)行約束,其實(shí)這兩者沒有明確的分別,它們都可以對(duì)控件的位置與尺寸起到作用。

兩種語法

1)手動(dòng)添加約束(蘋果官方API)

/**
 *  這個(gè)是系統(tǒng)默認(rèn)添加約束的方法,它是NSLayoutConstraint的類方法
 *
 *  @param view1      傳入想要添加約束的控件
 *  @param attr1      傳入想要添加約束的方向,這個(gè)枚舉值有很多,可以自己看看
 *  @param relation   傳入與約束值的關(guān)系,大于,等于還是小于
 *  @param view2      傳入被參照對(duì)象
 *  @param attr2      傳入被參照對(duì)象所被參照的方向,如頂部,左邊,右邊等等
 *  @param multiplier 傳入想要的間距倍數(shù)關(guān)系
 *  @param c          傳入最終的差值
 *
 *  @return NSLayoutConstraint對(duì)象
 */
+(instancetype)constraintWithItem:(id)view1 
                        attribute:(NSLayoutAttribute)attr1 
                        relatedBy:(NSLayoutRelation)relation 
                           toItem:(id)view2 
                        attribute:(NSLayoutAttribute)attr2 
                       multiplier:(CGFloat)multiplier 
                         constant:(CGFloat)c

//一部分NSLayoutAttribute枚舉值
    NSLayoutAttributeLeft = 1,//控件左邊
    NSLayoutAttributeRight,//控件右邊
    NSLayoutAttributeTop,
    NSLayoutAttributeBottom,
    NSLayoutAttributeLeading,//控件左邊
    NSLayoutAttributeTrailing,//控件右邊
    NSLayoutAttributeWidth,//控件的寬
    NSLayoutAttributeHeight,//控件的高
    NSLayoutAttributeCenterX,//豎直方向中點(diǎn)
    NSLayoutAttributeCenterY,//水平方向中點(diǎn)

這個(gè)方法的參數(shù)我很想用形象的語言描述出來,但是還是想不出,更多需要大家從下面的代碼中傳入的參數(shù)去體會(huì)

    //創(chuàng)建redView
    UIView *redView = [[UIView alloc]init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];
    
    //創(chuàng)建redView第一個(gè)約束,相對(duì)self.view的左邊緣間距20
    NSLayoutConstraint * redLeftLc = [NSLayoutConstraint constraintWithItem:redView
                                                                  attribute:NSLayoutAttributeLeftMargin
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:self.view
                                                                  attribute:NSLayoutAttributeLeft
                                                                 multiplier:1.0f
                                                                   constant:20.0];
    
    //只有在沒有參照控件的情況下,約束才加到自身,不然加到父控件上
    [self.view addConstraint:redLeftLc];
    
    //創(chuàng)建redView第二個(gè)約束,相對(duì)self。view的底邊緣間距20
    NSLayoutConstraint *redBottomLc = [NSLayoutConstraint constraintWithItem:redView
                                                                   attribute:NSLayoutAttributeBottom
                                                                   relatedBy:NSLayoutRelationEqual
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeBottomMargin
                                                                  multiplier:1.0f
                                                                    constant:-20];//由于是redview相對(duì)self.view往上減20,所以是-20
    //添加約束
    [self.view addConstraint:redBottomLc];
    
    //這里直接設(shè)置自身寬為50
    NSLayoutConstraint * redWLc = [NSLayoutConstraint constraintWithItem:redView
                                                               attribute:NSLayoutAttributeWidth
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50.0f];
    //由于沒有參照物,所以約束添加于自身身上
    [redView addConstraint:redWLc];
    
    //創(chuàng)建最后一個(gè)約束,自身的高
    NSLayoutConstraint * redHLc = [NSLayoutConstraint constraintWithItem:redView
                                                               attribute:NSLayoutAttributeHeight
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50];
    //由于沒有參照物,所以約束添加于自身身上
    [redView addConstraint:redHLc];     

運(yùn)行的效果圖


接下來我們繼續(xù)增加需求,在紅色方塊的右邊放一個(gè)離它20間距,離self.view底部也間距20,寬高相等的藍(lán)色方塊

    //先創(chuàng)建一個(gè)一個(gè)藍(lán)色的view添加到視圖上,剩下的就是用autolayout來設(shè)置它的“frame”了
    UIView *blueView = [[UIView alloc]init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];
    self.blueView = blueView;
    
    //創(chuàng)建第一個(gè)約束,左邊間距,由于是想要與紅色有20的間距,那么參照參數(shù)“toItem”就應(yīng)該填redView
    NSLayoutConstraint *blueLeft = [NSLayoutConstraint constraintWithItem:blueView
                                                                attribute:NSLayoutAttributeLeft
                                                                relatedBy:NSLayoutRelationEqual
                                                                   toItem:redView
                                                                attribute:NSLayoutAttributeRight
                                                               multiplier:1.0f
                                                                 constant:20.0f];
    //與其他控件發(fā)生約束,所以約束添加到父控件上
    [self.view addConstraint:blueLeft];
    
    //現(xiàn)在我們已經(jīng)可以確定自己水平方向的位置了,還差垂直方向的位置,現(xiàn)在我們來創(chuàng)建第二個(gè)約束,參照物依然是紅色方塊,需求是要離self.view底部20間距,這不是正好和紅色一樣么,那么我們可以直接與紅色方塊底部對(duì)齊就行了
    NSLayoutConstraint *blueBottom = [NSLayoutConstraint constraintWithItem:blueView
                                                                  attribute:NSLayoutAttributeBottom
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:redView
                                                                  attribute:NSLayoutAttributeBottom
                                                                 multiplier:1.0f
                                                                   constant:0.0f];//與紅色方塊底部對(duì)齊,倍數(shù)1.0f.差值0.0f
    //與其他控件發(fā)生約束,所以約束添加到父控件上
    [self.view addConstraint:blueBottom];
    
    //剩下兩個(gè)約束差不多,我就一并描述了,它們都以redView為參照,與其等寬等高
    NSLayoutConstraint *blueW = [NSLayoutConstraint constraintWithItem:blueView
                                                             attribute:NSLayoutAttributeWidth
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:redView
                                                             attribute:NSLayoutAttributeWidth
                                                            multiplier:1.0f
                                                              constant:0.0f];
    [self.view addConstraint:blueW];
    
    
    NSLayoutConstraint *blueH = [NSLayoutConstraint constraintWithItem:blueView
                                                             attribute:NSLayoutAttributeHeight
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:redView
                                                             attribute:NSLayoutAttributeHeight
                                                            multiplier:1.0f
                                                              constant:0.0f];
    [self.view addConstraint:blueH];

接下來看看效果圖


小結(jié):
1.其實(shí)Autolayout的思想非常簡(jiǎn)單,剛開始使用的時(shí)候不要想著馬上一氣呵成,最好一個(gè)控件一個(gè)控件的實(shí)現(xiàn)依賴,分別滿足其位置與尺寸的需求,如果一下子幾個(gè)控件一起弄的話,往往大家犯錯(cuò)是犯在約束添多了,而不是添少了。
2.就如上面的例子,很多人會(huì)在設(shè)置了與紅色等高等寬后,還同時(shí)去添加頂部對(duì)齊與底部對(duì)齊,這樣高度就重復(fù)設(shè)置了,他會(huì)忽略了,上下同時(shí)對(duì)齊不僅給予了垂直位置,也給予了高度,所以思路必須清晰!

Autolayout 下添加動(dòng)畫

我將在藍(lán)色方塊的右邊再加個(gè)同樣大小的黃色方塊,然后,要求點(diǎn)擊屏幕,然后藍(lán)色方塊被移除,黃色方塊替代藍(lán)色方塊的位置

還有一個(gè)autolayout的知識(shí)點(diǎn):優(yōu)先級(jí)(priority)

    //一如往常,先創(chuàng)建黃色View
    UIView *yellowV = [[UIView alloc]init];
    yellowV.backgroundColor = [UIColor yellowColor];
    yellowV.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:yellowV];
    
    //開始創(chuàng)建約束,第一個(gè)約束是什么呢?一看就知道是左間距約束啦
    NSLayoutConstraint *yellowLeft = [NSLayoutConstraint constraintWithItem:yellowV
                                                                  attribute:NSLayoutAttributeLeft
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:blueView attribute:NSLayoutAttributeRight
                                                                 multiplier:1.0f
                                                                   constant:20];
    //與其他控件發(fā)生約束,所以約束添加到父控件上
    [self.view addConstraint:yellowLeft];
    
    //添加底部約束
    NSLayoutConstraint *yellowBottom = [NSLayoutConstraint constraintWithItem:yellowV
                                                                    attribute:NSLayoutAttributeBottom
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:self.view
                                                                    attribute:NSLayoutAttributeBottom
                                                                   multiplier:1.0f
                                                                     constant:-20];
    //與其他控件發(fā)生約束,所以約束添加到父控件上
    [self.view addConstraint:yellowBottom];
    
    //這里我直接設(shè)置寬高約束了,就省事不加參照控件了
    NSLayoutConstraint *yellowW = [NSLayoutConstraint constraintWithItem:yellowV
                                                               attribute:NSLayoutAttributeWidth
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50.0f];
    [yellowV addConstraint:yellowW];
    
    
    NSLayoutConstraint *yellowH = [NSLayoutConstraint constraintWithItem:yellowV
                                                               attribute:NSLayoutAttributeHeight
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50.0f];
    [yellowV addConstraint:yellowH];

運(yùn)行效果


接下來我再給黃色View添加一個(gè)約束,這個(gè)約束涉及到優(yōu)先級(jí),大家注意看代碼了哈

//對(duì)黃色View添加約束,約束黃色view與紅色View的間距為20
NSLayoutConstraint *yellowAnotherLeft = [NSLayoutConstraint constraintWithItem:yellowV
                                                                     attribute:NSLayoutAttributeLeft
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:redView
                                                                     attribute:NSLayoutAttributeRight
                                                                    multiplier:1.0f
                                                                      constant:20];
UILayoutPriority priority = 250;//設(shè)置優(yōu)先級(jí)
yellowAnotherLeft.priority = priority;

//與其他控件發(fā)生約束,所以約束添加到父控件上
[self.view addConstraint:yellowAnotherLeft];        

想必大家應(yīng)該看出些端倪了,我在前面已經(jīng)給黃色View添加了對(duì)藍(lán)色View間距位20的view,現(xiàn)在又給黃色view對(duì)紅色View添加一個(gè)間距20的約束,這很明顯是不可能出現(xiàn)的情況,黃色View怎么可能同時(shí)做到這兩個(gè)約束呢,用術(shù)語來說就是約束沖突,但是大家注意看這段代碼

UILayoutPriority priority = 250;//設(shè)置優(yōu)先級(jí)
  1. 我給yellowAnotherLeft這個(gè)約束添加了優(yōu)先級(jí),優(yōu)先級(jí)的范圍是0~1000,數(shù)字越大,優(yōu)先級(jí)越高,在不設(shè)置的情況下默認(rèn)為1000

  2. 這說明了,我最后添加的這個(gè)約束的優(yōu)先級(jí)是低的,這個(gè)約束只有在它的沖突約束被抹掉后,它才能實(shí)現(xiàn)

  3. 也就是說,我把藍(lán)色view移除后,黃色View相對(duì)于藍(lán)色View左間距20這個(gè)約束就不成立了,那么黃色view會(huì)自動(dòng)的變?yōu)榕c紅色View間距20

讓我們最后加幾行代碼,來實(shí)現(xiàn)這個(gè)動(dòng)畫吧!

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //先把藍(lán)色方塊從父視圖上移除
    [self.blueView removeFromSuperview];
    //動(dòng)畫更新界面
    [UIView animateWithDuration:1.0f animations:^{
        [self.view layoutIfNeeded];
    }];
}   

autolayout的動(dòng)畫就是這樣實(shí)現(xiàn)的,將操作代碼走完后,再讓動(dòng)畫塊去更新界面,動(dòng)畫就出來了,效果如下:


2)VFL(visual format language)

需求:適配iPhone6,在RootViewController的view上添加一個(gè)新的view,讓這個(gè)新的view無論屏幕橫屏還是豎屏?xí)r候都距離其superview的邊緣20

H:|-20-[newView]-20-|

V:|-20-[newView]-20-|

每一個(gè) [] 中表示一個(gè)視圖或一個(gè)控件;V 表示垂直約束,H 表示水平約束,然后兩個(gè)視圖之間的 -0- 的意思就很簡(jiǎn)單了,意思就是這兩個(gè)視圖之間間隔為0

比如:
V:[view0(67)]-0-[view1(67)]-0-[view2(67)]-0-[view3(67)]-0-[view4(67)]-0-|

self.view.translatesAutoresizingMaskIntoConstraints = NO;
 
UIView *newView = [UIView new];
newView.backgroundColor = [UIColor greenColor];
[self.view addSubview:newView];
newView.translatesAutoresizingMaskIntoConstraints = NO;

NSMutableArray *constraintArray = [NSMutableArray array];
    
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:NSDictionaryOfVariableBindings(newView,self.view)]];
    
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[newView]-20-|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:NSDictionaryOfVariableBindings(newView,self.view)]];
[self.view addConstraints:constraintArray];

運(yùn)行效果

第三方庫 Masonry

  1. VFL的約束創(chuàng)建非常宏觀,如果既要照顧語法講解,又要照顧約束理解.
  2. Masonry的約束添加思維其實(shí)與蘋果原API的添加思維是相同的,只是Masonry語法更簡(jiǎn)潔,代碼更優(yōu)美

示例

需求:如下所示


實(shí)現(xiàn)如下:

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];
    
[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); // 設(shè)置寬度為self.view的一半,multipliedBy是倍數(shù)的意思,也就是,使寬度等于self.view寬度的0.5倍
   make.height.equalTo(self.view.mas_height).multipliedBy(0.5);// 設(shè)置高度為self.view的一半。

}];


[blueView mas_makeConstraints:^(MASConstraintMaker *make) {

   make.width.and.height.equalTo(redView); // 跟redview等寬高
   make.top.equalTo(redView.mas_top); // 與redview頂部對(duì)齊
   make.leading.equalTo(redView.mas_right); // 與 redview的間隔為0

}];

[yellow mas_makeConstraints:^(MASConstraintMaker *make) {

   make.width.and.height.equalTo(redView); // 跟redview等寬高
   make.top.equalTo(redView.mas_bottom); // 與 redview的間隔為0
   make.leading.equalTo(redView); // 與redvie左對(duì)齊

}];

[green mas_makeConstraints:^(MASConstraintMaker *make) {

   make.width.and.height.equalTo(redView); // 跟redview等寬高
   make.top.equalTo(yellow.mas_top); // 與yellow頂部對(duì)齊
   make.leading.equalTo(yellow.mas_right); // 與 yellow的間隔為0

}];

PS:需要下載第三庫 Masonry ,并導(dǎo)入 #import "Masonry.h"

Masonry 下的 Autolayout Animation

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];
self.greenView = 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);
}]; 

讓我們最后加幾行代碼,來實(shí)現(xiàn)這個(gè)動(dòng)畫吧!

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //先把綠色方塊從父視圖上移除
    [self.greenView removeFromSuperview];
    //動(dòng)畫更新界面
    [UIView animateWithDuration:1.0f animations:^{
        [self.view layoutIfNeeded];
    }];
}

運(yùn)行效果


總結(jié) Autolayout 使用

  1. 以后一律使用autolayout嗎?除了在storyboard中使用autolayout,代碼方式autolayout如何使用?

    • 當(dāng)需要展示的內(nèi)容很多并且尺寸不固定;
    • 程序需支持屏幕旋轉(zhuǎn)(主要是iPad程序,iPhone程序橫屏的場(chǎng)景有點(diǎn)非主流);
    • 程序通用于iPhone和iPad;
  2. 使用autolayout 利弊

    • 好處:可視化,實(shí)現(xiàn)簡(jiǎn)單功能很節(jié)省時(shí)間
    • 壞處:storyboard 使用 autolayout,移動(dòng)一個(gè)控件就會(huì)讓弄亂那些約束;
  3. autolayout有沒有局限性和解決不了的問題?兼容性怎么樣?效率怎么樣

    • autolayout對(duì)view transforms支持的不好,這里有帖子詳細(xì)描述了這個(gè)問題
    • 至于兼容性,只從iOS6就已經(jīng)提出了autolayout的概念,大部分用戶應(yīng)該是使用iOS7和iOS8系統(tǒng),所以兼容性問題不會(huì)太大,但size class是iOS8才有的概念,所以還有有一定的適配工作量

參考的帖子

iOS Autolayout解讀

iOS Autolayout之Masonry解讀

storyboard中autolayout和size class的使用詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,595評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,814評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,224評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,444評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,988評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,804評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,998評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評(píng)論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,237評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評(píng)論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,706評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,993評(píng)論 2 374

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