Autolayout中Hugging和Compression使用注意,autolayouthugging
前言
本文主要側重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屬性值有預設值:
為什麼會有不一樣的值?那麼先看一下 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];