AutoLayout


隨着iPhone設備出現了不同的尺寸,iOS6.0以后storyboard和xib文件新增了一個Use Auto Layout選項,用來實現自動布局。當你勾選上這個選項,以前傳統的布局方式將不能正常工作。一旦使用了自動布局,就要忘記 Frame 的概念!

要判斷UIView是否可以使用自動布局,可以使用如下方法:

if ([self.view respondsToSelector:@selector(addConstraints:)])
{
    //自動布局
}
else
{
    //傳統布局
}

可以通過-layoutIfNeeded和-setNeedsUpdateConstraints兩個方法來刷新約束的改變,使UIView重新布局。layoutIfNeeded是調整布局,也就是view的位置,一般是對subviews作用。setNeedsDisplay涉及到redraw,也就是重繪,一般都是對receiver作用。

layoutIfNeeded

使用此方法強制立即進行layout,從當前view開始,此方法會遍歷整個view層次(包括superviews)請求layout。因此,調用此方法會強制整個view層次布局。

setNeedsUpdateConstraints

當一個自定義view的某個屬性發生改變,並且可能影響到constraint時,需要調用此方法去標記constraints需要在未來的某個點更新,系統然后調用updateConstraints.

添加約束一般要遵循下面的規則:

  • 對於兩個同層級view之間的約束關系,添加到他們的父view上:

  • 對於兩個不同層級view之間的約束關系,添加到他們最近的共同父view上:

  • 對於有層次關系的兩個view之間的約束關系,添加到層次較高的父view上:

 

下面的例子演示了通過設定控件邊界距離,從而確定控件尺寸:

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:@"測試按鈕" forState:UIControlStateNormal];
[button sizeToFit];
[button setBackgroundColor:[UIColor yellowColor]];
button.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:button];

NSLayoutConstraint *constraint;

//上邊距
constraint = [NSLayoutConstraint
              constraintWithItem:button
              attribute:NSLayoutAttributeTop
              relatedBy:NSLayoutRelationEqual
              toItem:self.view
              attribute:NSLayoutAttributeTop
              multiplier:1.0f
              constant:50.0f];
[self.view addConstraint:constraint];

//左邊距
constraint = [NSLayoutConstraint
              constraintWithItem:button
              attribute:NSLayoutAttributeLeading
              relatedBy:NSLayoutRelationEqual
              toItem:self.view
              attribute:NSLayoutAttributeLeading
              multiplier:1.0f
              constant:100.0f];
[self.view addConstraint:constraint];

//右邊距
constraint = [NSLayoutConstraint
              constraintWithItem:button
              attribute:NSLayoutAttributeTrailing
              relatedBy:NSLayoutRelationEqual
              toItem:self.view
              attribute:NSLayoutAttributeTrailing
              multiplier:1.0f
              constant:-100.0f];
[self.view addConstraint:constraint];

//下邊距
constraint = [NSLayoutConstraint
              constraintWithItem:button
              attribute:NSLayoutAttributeBottom
              relatedBy:NSLayoutRelationEqual
              toItem:self.view
              attribute:NSLayoutAttributeBottom
              multiplier:1.0f
              constant:-350.0f];
[self.view addConstraint:constraint];

 

下面的例子設定了控件在父容器中水平垂直居中:

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:@"測試按鈕" forState:UIControlStateNormal];
[button sizeToFit];
[button setBackgroundColor:[UIColor yellowColor]];
button.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:button];

NSLayoutConstraint *constraint;

//水平居中
constraint = [NSLayoutConstraint
              constraintWithItem:button
              attribute:NSLayoutAttributeCenterX
              relatedBy:NSLayoutRelationEqual
              toItem:self.view
              attribute:NSLayoutAttributeCenterX
              multiplier:1.0f
              constant:0.0f];
[self.view addConstraint:constraint];

//垂直居中
constraint = [NSLayoutConstraint
              constraintWithItem:button
              attribute:NSLayoutAttributeCenterY
              relatedBy:NSLayoutRelationEqual
              toItem:self.view
              attribute:NSLayoutAttributeCenterY
              multiplier:1.0f
              constant:0.0f];
[self.view addConstraint:constraint];

 

下面的例子直接設定了控件的尺寸:

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:@"測試按鈕" forState:UIControlStateNormal];
[button sizeToFit];
[button setBackgroundColor:[UIColor yellowColor]];
button.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:button];

NSLayoutConstraint *constraint;

//設置寬度
constraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:130.0f];
[self.view addConstraint:constraint];

//設置高度
constraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:70.0f];
[self.view addConstraint:constraint];

 

除了上面添加約束的方法,還有一種全新的方法:Visual Format Language(可視格式語言),這種語言是對視覺描述的一種抽象。基本用法如下:

UIButton *buttonA = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[buttonA setTitle:@"AAA" forState:UIControlStateNormal];
[buttonA sizeToFit];
[buttonA setBackgroundColor:[UIColor yellowColor]];
buttonA.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:buttonA];

UIButton *buttonB = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[buttonB setTitle:@"BBB" forState:UIControlStateNormal];
[buttonB sizeToFit];
[buttonB setBackgroundColor:[UIColor yellowColor]];
buttonB.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:buttonB];


NSMutableArray *array = [NSMutableArray array];

//水平方向布局(從左向右)
[array addObjectsFromArray:[NSLayoutConstraint
                            constraintsWithVisualFormat:@"|-60-[buttonA(==90)]-30-[buttonB]"
                            options:NSLayoutFormatDirectionLeadingToTrailing
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(buttonA,buttonB)]];

//垂直方向布局(從上向下)
[array addObjectsFromArray:[NSLayoutConstraint
                            constraintsWithVisualFormat:@"V:|-100-[buttonB]-50-[buttonA]"
                            options:NSLayoutFormatDirectionLeadingToTrailing
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(buttonA,buttonB)]];

[self.view addConstraints:array];

 

constraintsWithVisualFormat方法的最后一個參數views需要提供一個字典,用來指明可視化字符串里出現控件名所對應的控件:

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(buttonA,buttonB);

for(NSString *key in viewsDictionary)
{
    NSLog(@"key:%@, value:%@",key,viewsDictionary[key]);
}
//key:buttonA, value:<UIButton: 0x8dc5850; frame = (0 0; 30 30); opaque = NO; layer = <CALayer: 0x8dc7270>>
//key:buttonB, value:<UIButton: 0x8dc8a90; frame = (0 0; 32 30); opaque = NO; layer = <CALayer: 0x8dc8b80>>

 

下面是兩個具有代表性的語句示例:

@"|-50-[buttonA(80@100)]-[buttonB(90@200)]-50-|"

這條語句的含義是:“左右邊距都為50,中間有兩個按鈕,相隔缺省寬度,一個控件寬度為80,約束優先級為100;另一個控件寬度為90,約束優先級為200”。實際運行后,發現buttonB的控件寬度為90,而buttonA的寬度為自適應寬度,並不是80像素;這是因為buttonB的約束優先級200大於buttonA的約束優先級,所以優先生效。可以把buttonA的優先級改的比buttonB大,就可以看到完全相反的結果。

 

@"V:[buttonA(80)]-20-[buttonB(==buttonA)]"

這條語句的含義是:“垂直方向有一個高度為80的buttonA,然后間隔20有一個和buttonA同樣高度的buttonB”

P.s. NSLayoutAttributeLeft/NSLayoutAttributeRight 和 NSLayoutAttributeLeading/NSLayoutAttributeTrailing的區別是left/right永遠是指左右,而leading/trailing在某些從右至左習慣的地區會變成,leading是右邊,trailing是左邊。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM