深入剖析AutoLayout 之 边距
03 Mar 2015iOS8为Auto Layout引入了基于margin的布局方式.
首先是NSLayoutAttribute新增了几种与margin相关的attribute:
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),而后UIView上也相应增加了几个方法:
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0); // default is NO - set to enable pass-through or cascading behavior of margins from this view’s parent to its children
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);很显然, 新增的方法需要与新增的attribute搭配使用. 那么margin究竟指什么? margin指视图内嵌的一段边距, 借由这段边距和上述margin属性, UI对象得以统一设定内部留白区域.
假设:
view.layoutMargins = UIEdgeInsetsMake(10, 10, 10, 10);
若:
[view addConstraint:[NSLayoutConstraint constraintWithItem:subview
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeTopMargin
multiplier:1.f
constant:0.f]];
则, 由于margin的存在, subview的top与view的top间距为10, 即margin的长度.
若:
subview.layoutMargins = UIEdgeInsetsMake(4, 4, 4, 4);
[view addConstraint:[NSLayoutConstraint constraintWithItem:subview
attribute:NSLayoutAttributeTopMargin
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeTopMargin
multiplier:1.f
constant:0.f]];
则, 由于margin的存在, subview的top与view的top间距为6, 即margin的差.
-layoutMarginsDidChange默认实现什么都不做, 仅供子类override, 以响应layoutMargins的改变.
preservesSuperviewLayoutMargins的作用如同其名, 指子视图使用自身的margin作为attribute时, 是否同时要求子视图满足父视图的margin限制. 例如:
superview.layoutMargins = UIEdgeInsetsMake(10, 10, 10, 10);
view.layoutMargins = UIEdgeInsetsMake(4, 4, 4, 4);
view.preservesSuperviewLayoutMargins = YES;
[superview addConstraint:[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeTop
multiplier:1.f
constant:1.f]]; // 注意, 非0
[view addConstraint:[NSLayoutConstraint constraintWithItem:subview
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeTopMargin
multiplier:1.f
constant:0.f]];
由于preservesSuperviewLayoutMargins为YES, subview需要同时满足于view和superview的margin, 则subview的top距view和superview的top为9.
应该说, margin是相当有用的工具. 上下左右统一留白的布局非常常见, 这时, 使用margin可以跨层次在一处代码设定边距. 遗憾的是, iOS8作为baseSDK还不知道要等到什么时候.