發(fā)現(xiàn)問題
在IB中拖放tableView,大小為設(shè)置為屏幕大小后,添加了四個(gè)方向的約束绍载,發(fā)現(xiàn)诡宗,約束的值居然不是和想象中不太一樣,不是0击儡。
接著打開attribute inspector,發(fā)現(xiàn)約束信息如下:
在這里發(fā)現(xiàn)Second Item是superView 的 leading Margin. 而不是superView的leading塔沃,所以約束的值不是0,但leading margin又是什么阳谍?
Layout Magrin
通過查找文檔蛀柴,發(fā)現(xiàn)這是iOS 8 以后,UIView 新增的一個(gè)屬性矫夯,layoutMargins. 表示一個(gè)View的內(nèi)邊距鸽疾。
文檔
@property(nonatomic) UIEdgeInsets layoutMargins;
The default spacing to use when laying out content in the view.
typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} UIEdgeInsets;
這個(gè)屬性類似Android中的padding,用于父View設(shè)置子View布局的內(nèi)邊距训貌。
The default margins are eight points on each side.
默認(rèn)值是8個(gè)點(diǎn)制肮,可修改。
If the view is a view controller’s root view, the system sets and manages the margins. The top and bottom margins are set to zero points. The side margins vary depending on the current size class, but can be either 16 or 20 points. You cannot change these margins.
但如果递沪,是ViewController的rootView豺鼻,layoutMargins 是系統(tǒng)設(shè)置和控制的,不能修改款慨。(文章最開始的tableView到 leading Margin 約束為 -16.就說明儒飒,left margin是16點(diǎn)。)
到這里檩奠,其實(shí)對layoutMargins理解都較為清晰约素,但是文檔中還提到了一個(gè)與layoutMargins 相關(guān)的屬性: preservesSuperviewLayoutMargins
When the edge of your view is close to the edge of the superview and the preservesSuperviewLayoutMargins property is YES, the actual layout margins may be increased to prevent content from overlapping the superview’s margins.
讀完感覺字面意思都懂,但就是不知道是什么意思笆凌。
preservesSuperviewLayoutMargins
@property(nonatomic) BOOL preservesSuperviewLayoutMargins;
A Boolean value indicating whether the current view also respects the margins of its superview.
The default value of this property is NO.
一個(gè)BOOL值圣猎,決定當(dāng)前View布局是否也考慮父View的layoutMargins.
默認(rèn)是NO.
到這里還是暈的,沒看懂這個(gè)屬性是干嘛乞而,繼續(xù)看文檔送悔。
文檔
When the value of this property is YES, the superview’s margins are also considered when laying out content. This margin affects layouts where the distance between the edge of a view and its superview is smaller than the corresponding margin.
當(dāng)這個(gè)屬性是YES的時(shí)候,父view的layoutMargins會被考慮到當(dāng)前View的布局中爪模。也就是說欠啤,當(dāng)前View和父View的內(nèi)邊距,小于父View相應(yīng)layoutMargins中對應(yīng)的內(nèi)邊距時(shí)屋灌,父View的內(nèi)邊距會決定當(dāng)前View的布局洁段。還是有些抽象。
For example, you might have a content view whose frame precisely matches the bounds of its superview. When any of the superview’s margins is inside the area represented by the content view and its own margins, UIKit adjusts the content view’s layout to respect the superview’s margins. The amount of the adjustment is the smallest amount needed to ensure that content is also inside the superview’s margins.
這里大概的意思就是共郭,你有一個(gè)contentView祠丝,它的大小和父View一樣大的你設(shè)置了contentView的preservesSuperviewLayoutMargins為YES疾呻,當(dāng)你對contentView中的子View進(jìn)行布局的時(shí)候,如果有子View的所在位置(比如:子View到contentView的左邊距写半,小于父View的LayoutMargin 對應(yīng)的左內(nèi)邊距)UIKit就會對子View進(jìn)行一些調(diào)整岸蜗。
感覺看了這一段稍微清晰了一些,可是寫代碼想實(shí)現(xiàn)一個(gè)demo的時(shí)候叠蝇,發(fā)現(xiàn)這個(gè)preservesSuperviewLayoutMargins屬性好像并沒有什么卵用璃岳。
最后再Google上搜到了這篇文章。
iOS8 Day-by-Day :: Day 32 :: Layout Margins
然后自己實(shí)現(xiàn)了一個(gè) demo 如下
- (void)viewDidLoad {
[super viewDidLoad];
//創(chuàng)建一個(gè)紅色的View悔捶,大小和手機(jī)屏幕一樣大铃慷,
//layoutMargin 為(100,100蜕该,100枚冗,100)
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.translatesAutoresizingMaskIntoConstraints = NO;
redView.layoutMargins = UIEdgeInsetsMake(100, 100, 100, 100);
[self.view addSubview:redView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[redView]-(0)-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(redView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[redView]-(0)-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(redView)]];
//創(chuàng)建一個(gè)綠色的View,作為我們的ContentView蛇损,父View為紅色的View
//約束為到紅色View各邊距為10赁温,但紅色View 的layoutMargin 還是再綠色View內(nèi)
//設(shè)置綠色View preservesSuperviewLayoutMargins 為YES
UIView *greenView = [[UIView alloc] init];
greenView.backgroundColor = [UIColor greenColor];
greenView.translatesAutoresizingMaskIntoConstraints = NO;
greenView.preservesSuperviewLayoutMargins = YES;
[redView addSubview:greenView];
[redView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[greenView]-(10)-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(greenView)]];
[redView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(10)-[greenView]-(10)-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(greenView)]];
//創(chuàng)建一個(gè)藍(lán)色View,作為綠色View的子View
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
blueView.translatesAutoresizingMaskIntoConstraints = NO;
[greenView addSubview:blueView];
//注意淤齐,leading 約束對應(yīng)的第二item 屬性為 leading.margin
[greenView addConstraint: [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:greenView attribute:NSLayoutAttributeLeadingMargin multiplier:1.0 constant:0.0]];
// trailing 屬性 為父View trailig - 8.0// 8.0 是默認(rèn)layout Margin
[greenView addConstraint: [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:greenView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-8.0]];
[greenView addConstraint: [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:greenView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[greenView addConstraint: [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:greenView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
}
總結(jié)
最后總結(jié)一下preservesSuperviewLayoutMargins生效的要點(diǎn):(如果總結(jié)的不對希望大家指正~)
1.preservesSuperviewLayoutMargins 只在自動布局情況下生效
2.contentView(設(shè)置preservesSuperviewLayoutMargins的View)的父View的LayoutMargin中股囊,至少存在contentView 某一個(gè)方向到父View的邊距,小于父View LayoutMargin 對應(yīng)的內(nèi)邊距更啄。(就比如上面栗子中稚疹,綠色View到紅色View的左邊距是10,紅色View的LayoutMargin中對應(yīng)的左內(nèi)邊距為100)
3.設(shè)置自動布局約束的時(shí)候祭务,一定要設(shè)置Margin相關(guān)的約束(iOS8以上有效)
typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
...
NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
};
思考
現(xiàn)在基本上弄清楚了内狗,LayoutMargin和preservesSuperviewLayoutMargins屬性,以及如何使用义锥,但是對他們在自動布局的實(shí)際使用場景還是沒有思考太清楚柳沙,沒有明白蘋果為什么會設(shè)置這兩個(gè)屬性,特別是preservesSuperviewLayoutMargins屬性拌倍。 = =