iOS: 在代碼中使用Autolayout

來源:互聯網
上載者:User

標籤:style   blog   http   color   io   os   使用   ar   for   

原理:IOS6.0 之後,蘋果最佳化了UI介面的布局方式,提出了自動布局的概念,和之前的autoresizing相比功能更強大。子視圖基於父視圖的自動布局顯示。都是父視圖去添加對子視圖的約束。

在這裡主要說的是通過代碼對自動布局視圖的實現。

代碼中一般用到的有兩個添加約束的方式:

1.- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);

2.- (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0);

<

在使用自動布局之前要對子視圖的布局方式進行調整,用到這個UIView的屬性。

- (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES

需要將其設定為NO;

>

下面用簡單例子說明一下:

(1) – 按比例縮放和優先順序

首先說按比例縮放,這是在Interface Builder中無法設定的內容。而在代碼中,使用NSLayoutConstraint類型的初始化函數中的multiplier參數就可以非常簡單的設定按比例縮放。同時也可以設定不同NSLayoutAttribute參數來達到意想不到的效果,比如“A的Width等於B的Height的2倍”這樣的效果。

 1    topLabel= [[UILabel alloc] initWithFrame:CGRectZero]; 2     topLabel.translatesAutoresizingMaskIntoConstraints = NO; 3     topLabel.backgroundColor = [UIColor lightGrayColor]; 4     topLabel.numberOfLines = 0; 5     topLabel.text = @"選我選我選我選我選我選我"; 6     topLabel.userInteractionEnabled = YES; 7     UITapGestureRecognizer *tt = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(nextContro)]; 8     [topLabel addGestureRecognizer:tt]; 9     [self.view addSubview:topLabel];10     11     secondLabel = [[UILabel alloc] initWithFrame:CGRectZero];12     secondLabel.translatesAutoresizingMaskIntoConstraints = NO;13     secondLabel.backgroundColor = [UIColor cyanColor];14     secondLabel.text = @"按我";15     secondLabel.userInteractionEnabled = YES;16     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeThirdLabel:)];17     [secondLabel addGestureRecognizer:tap];18     [self.view addSubview:secondLabel];19     20     thirdLabel = [[UILabel alloc] initWithFrame:CGRectZero];21     thirdLabel.translatesAutoresizingMaskIntoConstraints = NO;22     thirdLabel.backgroundColor = [UIColor purpleColor];23     thirdLabel.numberOfLines = 0;24     thirdLabel.text = str;25     [self.view addSubview:thirdLabel];

設定firstLabel的布局

1 NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:topLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0];2     NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:topLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.2 constant:0];3     4     [self.view addConstraint:widthConstraint];5     [self.view addConstraint:heightConstraint];

設定secondLabel的位置

1 //設定view之間長度相等,並且在試圖在邊緣內(超過邊緣自動往下)2     [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topLabel][secondLabel(==topLabel)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(topLabel, secondLabel)]];3     4     //設定高度,距頂部20,之間間隔10,secondLabel高度為30,只是上面對齊下面不對齊5     [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[topLabel(>[email protected])]-10-[secondLabel(==30)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(topLabel, secondLabel)]];

設定thirdLabel的位置並根據文本動態顯示高度

 1  //水平置中,始終距離父View底部20單位的距離。然後高度是父View高度的5分之一 2     //置中 3     [self.view addConstraint:[NSLayoutConstraint constraintWithItem:thirdLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; 4      //距離底部50,注意NSLayoutConstraint建立的constant是加在toItem參數的,所以需要-20。 5     [self.view addConstraint:[NSLayoutConstraint constraintWithItem:thirdLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-50]]; 6     //定義高度是父View的5分之一 7 //    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:thirdLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.5 constant:0]]; 8      9     NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:thirdLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0];10     constraint.priority = UILayoutPriorityDefaultHigh;11     [self.view addConstraint:constraint];12     //最小高度為15013     [thirdLabel addConstraint:[NSLayoutConstraint constraintWithItem:thirdLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1 constant:150]];14     15     //註冊KVO方法16     [thirdLabel addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:nil];
//KVO回掉- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{    if (object == thirdLabel && [keyPath isEqualToString:@"bounds"]) {//        thirdLabel.text = str;//        thirdLabel.text = @"ha";//        thirdLabel.text = NSStringFromCGSize(thirdLabel.bounds.size);    }}

可以設定空間展示的動畫效果

 

 [UIView animateWithDuration:0.5 animations:^{        [self.view layoutIfNeeded];    }];

 

 

 

(2) – intrinsicContentSize和Content Hugging Priority

先說intrinsicContentSize,也就是控制項的內建大小。比如UILabel,UIButton等控制項,他們都有自己的內建大小。控制項的內建大小往往是由控制項本身的內容所決定的,比如一個UILabel的文字很長,那麼該UILabel的內建大小自然會很長。控制項的內建大小可以通過UIView的intrinsicContentSize屬性來擷取內建大小,也可以通過invalidateIntrinsicContentSize方法來在下次UI規劃事件中重新計算intrinsicContentSize。如果直接建立一個原始的UIView對象,顯然它的內建大小為0。

繼續用代碼來寫Autolayout,先寫一個輔助方法來快速設定UIView的邊距限制:

1 //設定Autolayout中的邊距輔助方法2 - (void)setEdge:(UIView*)superview view:(UIView*)view attr:(NSLayoutAttribute)attr constant:(CGFloat)constant3 {4     [superview addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:attr relatedBy:NSLayoutRelationEqual toItem:superview attribute:attr multiplier:1.0 constant:constant]];5 }

接下來,建立一個UIView,利用上面的輔助方法快速設定其在父控制項的左,上,右邊距為20單位。UIView預設是沒有intrinsicContentSize的。我們可以通過建立一個自訂的UIView來改寫intrinsicContentSize。

在MyView裡添加:

- (CGSize)intrinsicContentSize {    return CGSizeMake(0, 100); //controll設定了left以及right,故這裡的width沒效果}

 

如下代碼:

 1  //view1 2     MyView *view1 = [[MyView alloc] init]; 3     view1.backgroundColor = [UIColor yellowColor]; 4     //不允許AutoresizingMask轉換成Autolayout 5     view1.translatesAutoresizingMaskIntoConstraints = NO; 6     [self.view addSubview:view1]; 7     //設定左,上,右邊距為20. 8     [self setEdge:self.view view:view1 attr:NSLayoutAttributeLeft constant:20]; 9     [self setEdge:self.view view:view1 attr:NSLayoutAttributeTop constant:80];10     [self setEdge:self.view view:view1 attr:NSLayoutAttributeRight constant:-20];11     12     13     //view214     MyView *view2 = [MyView new];15     view2.backgroundColor = [UIColor greenColor];16     //不允許AutoresizingMask轉換成Autolayout17     view2.translatesAutoresizingMaskIntoConstraints = NO;18     [self.view addSubview:view2];19     //設定左,下,右邊距為20.20     [self setEdge:self.view view:view2 attr:NSLayoutAttributeLeft constant:20];21     [self setEdge:self.view view:view2 attr:NSLayoutAttributeBottom constant:-80];22     [self setEdge:self.view view:view2 attr:NSLayoutAttributeRight constant:-20];
1 //設定兩個View上下間距為202     [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view2 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view1 attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20]];

設定view的Content Hugging Priority.Content Hugging Priority代表控制項拒絕展開的優先順序。優先順序越高,控制項會越不容易被展開。

還有一個Content Compression Resistance Priority代表控制項拒絕壓縮內建空間的優先順序。優先順序越高,控制項的內建空間會越不容易被壓縮。而這裡的內建空間,就是上面講的UIView的intrinsicContentSize。

可以直接通過UIView的setContentHuggingPriority:forAxis方法來設定控制項的Content Hugging Priority,其中forAxis參數代表橫向和縱向,本例中只需要設定縱向,所以傳入UILayoutConstraintAxisVertical。整句代碼:

[view2 setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];

 

關於constraintsWithVisualFormat:函數介紹:

 constraintsWithVisualFormat:參數為NSString型,指定Contsraint的屬性,是垂直方向的限定還是水平方向的限定,參數定義一般如下:

V:|-(>=XXX) :表示垂直方向上相對於SuperView大於、等於、小於某個距離

若是要定義水平方向,則將V:改成H:即可

在接著後面-[]中括弧裡面對當前的View/控制項 的高度/寬度進行設定;

options:字典類型的值;這裡的值一般在系統定義的一個enum裡面選取

metrics:nil;一般為nil ,參數類型為NSDictionary,從外部傳入 //衡量標準

views:就是上面所加入到NSDictionary中的綁定的View

在這裡要注意的是 AddConstraints  和 AddConstraint 之間的區別,一個添加的參數是NSArray,一個是NSLayoutConstraint

 

使用規則

|: 表示父視圖

  -:表示距離

  V:  :表示垂直

  H:  :表示水平

>= :表示視圖間距、寬度和高度必須大於或等於某個值

    <= :表示視圖間距、寬度和高度必須小宇或等於某個值

    == :表示視圖間距、寬度或者高度必須等於某個值

@  :>=、<=、==  限制   最大為  1000

 

1.|-[view]-|:  視圖處在父視圖的左右邊緣內

2.|-[view]  :   視圖處在父視圖的左邊緣

3.|[view]   :   視圖和父視圖左邊對齊

4.-[view]-  :  設定視圖的寬度高度

5.|-30.0-[view]-30.0-|:  表示離父視圖 左右間距  30

6.[view(200.0)] : 表示視圖寬度為 200.0

7.|-[view(view1)]-[view1]-| :表示視圖寬度一樣,並且在父視圖左右邊緣內

8. V:|-[view(50.0)] : 視圖高度為  50

9: V:|-(==padding)-[imageView]->=0-[button]-(==padding)-| : 表示離父視圖的距離

為Padding,這兩個視圖間距必須大於或等於0並且距離底部父視圖為 padding。

10:  [wideView(>[email protected])]  :視圖的寬度為至少為60 不能超過  700

11: 如果沒有聲明方向預設為  水平  V:

 

Demo地址:https://github.com/LiDechao/AutoLayout

iOS: 在代碼中使用Autolayout

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.