原文: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。
然後在.m檔案中改寫
intrinsicContentSize
方法,并傳回有效值,比如這樣:
//改寫UIView的intrinsicContentSize
- (CGSize)intrinsicContentSize
{
return CGSizeMake(70, 40);
}
接着修改最上面的代碼,把上面view1變量的類型從
UIView
替換成我們自定義的View:MyView類型:
MyView *view1 = [MyView new];
再次運作代碼,View會按照要求顯示在螢幕上:
接下來,按照同樣的方式,在下方添加另一個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];
運作後是這樣:
接下來,通過代碼加入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]];
運作結果:
OK,的确,此時view1和view2互相間隔20機關,但是view1被拉伸了。
接下來的任務就是做到如何不讓view1拉伸,而讓view2拉伸呢?這裡就需要使用控件的Content Hugging Priority,這個屬性在Xcode中的控件屬性中很常見,如下圖:
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];
運作結果:
轉載于:https://www.cnblogs.com/A--G/p/4667970.html