本文主要側重Autolayout
使用過程中,通過代碼和SB添加含有intrinsicSize
屬性控件約束的一些細節。
來自我的博客,歡迎訪問:To Be Independent.
Hugging和ComPRession 屬性
有很多關于這兩個概念的文章,比如stackoverflow上Cocoa Autolayout: content hugging vs content compression resistance priority。我覺得很形象的說明了設置了有什么用,但是還欠缺什么時候使用,即和`intrinsicSize`的關系。先來看下文檔上的說明:
- contentCompressionResistancePriorityForAxis://Returns the priority with which a view resists being made smaller than its intrinsic size.- contentHuggingPriorityForAxis://Returns the priority with which a view resists being made larger than its intrinsic size.
這么一看,就很明了:對于有 intrinsicSize 屬性的控件(如UILabel,UIButton等),如果當前的frame比顯示的content范圍大,那么設置的Hugging屬性起作用,否則設置的Compression屬性起作用。對于相應的數值,越大表明優先級越高,意味著當前的屬性占優。簡單的說,對于需要Hugging的情形,hugging屬性的值越大(優先級越高),那么表明控件需要緊湊的顯示。
Hugging和Compression屬性值有默認值:
- 對于純代碼添加的控件,Hugging默認250.0f,Compression默認 750.0f
- 通過SB添加,Hugging默認251.0f,Compression默認750.0f
為什么會有不一樣的值?那么先看一下 UILayoutPriority的取值:
static const UILayoutPriority UILayoutPriorityRequired NS_AVAILABLE_IOS(6_0) = 1000; // A required constraint. Do not exceed this.static const UILayoutPriority UILayoutPriorityDefaultHigh NS_AVAILABLE_IOS(6_0) = 750; // This is the priority level with which a button resists compressing its content.static const UILayoutPriority UILayoutPriorityDefaultLow NS_AVAILABLE_IOS(6_0) = 250; // This is the priority level at which a button hugs its contents horizontally.static const UILayoutPriority UILayoutPriorityFittingSizeLevel NS_AVAILABLE_IOS(6_0) = 50;// When you send -[UIView systemLayoutSizeFittingSize:], the size fitting most closely to the target size (the argument) is computed. UILayoutPriorityFittingSizeLevel is the priority level with which the view wants to conform to the target size in that computation. It's quite low. It is generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower.
由此可見,在設計的時候,iOS的開發人員考慮到類似UILabel的控件首要的是顯示所有的內容。
編程實現
通過一段代碼,加載一個button:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];button.translatesAutoresizingMaskIntoConstraints = NO;button.backgroundColor = [UIColor redColor];[button setTitle:@"a long long title" forState:UIControlStateNormal];[self.view addSubview:button];NSLayoutConstraint *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:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:100.0f];[self.view addConstraint:constraint];constraint = [[NSLayoutConstraint constraintWithItem:button1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:0 constant:50.0f];[self.view addConstraint:constraint];
如上添加的constraint,使得button的frame不足以顯示標題內容,注意上述constraint默認的優先級都是UILayoutPriorityRequired。因此我們可以通過修改最后一個寬度的constraint:
constraint.priority = UILayoutPriorityDefaultHigh - 1;
對于用SB添加的控件,也可以用類似的方法修改。至于為什么,SB中添加的如UILable的控件,當給其添加某個約束后,SB中Hugging屬性的值是251呢?這是為了默認可以顯示全內容。此時,你可以在sb中手動把空間尺寸變小,再把控件的某個屬性的constriant(width或tailing)的優先級設置為low。這時,你也可以在SB中發現相應的約束由藍色實線變成了藍色虛線。當然,如果compression約束起作用的情況下,約束也是藍色虛線。
與其它控件一起使用
如上單個控件可以正常使用,如果設置一個相鄰的控件,會有什么需要注意的嗎?答案是NO,什么都不需要操心,仍舊按之前的方法添加約束,這極大的簡化了工作量。
另外,這里需要說明的是,需要更新控件上文字的時候,為了有一個較好的動畫效果,需要:
[label.superView layoutIfNeeded];