天天看點

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

原文:http://www.mgenware.com/blog/?p=491

接上文:iOS: 在代碼中使用Autolayout (1) – 按比例縮放和優先級。

我們繼續來看在代碼中使用Autolayout的話題。先說

intrinsicContentSize

,也就是控件的内置大小。比如

UILabel

UIButton

等控件,他們都有自己的内置大小。控件的内置大小往往是由控件本身的内容所決定的,比如一個

UILabel

的文字很長,那麼該

UILabel

的内置大小自然會很長。控件的内置大小可以通過

UIView

intrinsicContentSize

屬性來擷取内置大小,也可以通過

invalidateIntrinsicContentSize

方法來在下次UI規劃事件中重新計算

intrinsicContentSize

。如果直接建立一個原始的

UIView

對象,顯然它的内置大小為0。

繼續用代碼來寫Autolayout,先寫一個輔助方法來快速設定

UIView

的邊距限制:

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

接下來,建立一個UIView,利用上面的輔助方法快速設定其在父控件的左,上,右邊距為20機關。如下代碼:

//view1
UIView *view1 = [UIView new];
view1.backgroundColor = [UIColor yellowColor];
//不允許AutoresizingMask轉換成Autolayout
view1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view1];
//設定左,上,右邊距為20.
[self setEdge:self.view view:view1 attr:NSLayoutAttributeLeft constant:20];
[self setEdge:self.view view:view1 attr:NSLayoutAttributeTop constant:20];
[self setEdge:self.view view:view1 attr:NSLayoutAttributeRight constant:-20];      

但是運作後會發現,界面上不會顯示任何東西。原因就是上面講的,

UIView

預設是沒有

intrinsicContentSize

的。我們可以通過建立一個自定義的

UIView

來改寫

intrinsicContentSize

比如,建立一個新的類型:MyView。

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

然後在.m檔案中改寫

intrinsicContentSize

方法,并傳回有效值,比如這樣:

//改寫UIView的intrinsicContentSize
- (CGSize)intrinsicContentSize
{
    return CGSizeMake(70, 40);
}      

接着修改最上面的代碼,把上面view1變量的類型從

UIView

替換成我們自定義的View:MyView類型:

MyView *view1 = [MyView new];      

再次運作代碼,View會按照要求顯示在螢幕上:

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

接下來,按照同樣的方式,在下方添加另一個MyView,要求其距離父控件邊距左,下,右各為20,代碼:

//view2
MyView *view2 = [MyView new];
view2.backgroundColor = [UIColor yellowColor];
//不允許AutoresizingMask轉換成Autolayout
view2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view2];
//設定左,下,右邊距為20.
[self setEdge:self.view view:view2 attr:NSLayoutAttributeLeft constant:20];
[self setEdge:self.view view:view2 attr:NSLayoutAttributeBottom constant:-20];
[self setEdge:self.view view:view2 attr:NSLayoutAttributeRight constant:-20];
      

運作後是這樣:

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

接下來,通過代碼加入Autolayout中的間距。指令view1和view2上下必須間隔20個機關,注意這裡要求view2在view1之下的20機關,是以建立

NSLayoutConstraint

中view2參數在前面。同時注意,view2的attribute參數是

NSLayoutAttributeTop

,而view1的attribute參數是

NSLayoutAttributeBottom

//設定兩個View上下間距為20
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:view2 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view1 attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20]];      

運作結果:

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

OK,的确,此時view1和view2互相間隔20機關,但是view1被拉伸了。

接下來的任務就是做到如何不讓view1拉伸,而讓view2拉伸呢?這裡就需要使用控件的Content Hugging Priority,這個屬性在Xcode中的控件屬性中很常見,如下圖:

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

Content Hugging Priority代表控件拒絕拉伸的優先級。優先級越高,控件會越不容易被拉伸。

而下面的Content Compression Resistance Priority代表控件拒絕壓縮内置空間的優先級。優先級越高,控件的内置空間會越不容易被壓縮。而這裡的内置空間,就是上面講的

UIView

intrinsicContentSize

是以,如果我們把view1(上圖中被拉伸的,在上面的View)的Content Hugging Priority設定一個更高的值,那麼當Autolayout遇到這種決定誰來拉伸的情況時,view1不會被優先拉伸,而優先級稍低的view2才會被拉伸。

可以直接通過

UIView

setContentHuggingPriority:forAxis

方法來設定控件的Content Hugging Priority,其中forAxis參數代表橫向和縱向,本例中隻需要設定縱向,是以傳入

UILayoutConstraintAxisVertical

。整句代碼:

//提高view1的Content Hugging Priority
[view1 setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
      

運作結果:

iOS: 在代碼中使用Autolayout (2) – intrinsicContentSize和Content Hugging Priority【轉】

轉載于:https://www.cnblogs.com/A--G/p/4667970.html