1. @interface UIView (UIConstraintBasedCompatibility)
2.
3. - (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0);
4. - (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag NS_AVAILABLE_IOS(6_0);
5.
6. + (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
7.
8. @end
默认情况下,View的autoresizing工作会根据当前位置自动设置约束。我们在使用代码写自己的约束布局代码时,必须设置当前View的translatesAutoresizingMaskIntoConstraints为NO,否则无法正常运作。IB默认是NO。
requiresConstraintBasedLayout :我们应该在自定义View中重写这个方法。如果我们要使用Auto Layout布局当前视图,应该设置为返回YES。
+ (BOOL)requiresConstraintBasedLayout //返回view是否是约束布局模式,ios6,返回值决定了是否是autoLayout布局模式。使用autolayout返回YES
Views
当用 Auto Layout 布局你的 view 的时候,确保在你父类中加入了下面的代码:
+ (BOOL)requiresConstraintBasedLayout
{
return YES;
}
-updateConstraints
// 调用在view 内部,而不是viewcontroller
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
requiresConstraintBasedLayout :我们应该在自定义View中重写这个方法。如果我们要使用Auto Layout布局当前视图,应该设置为返回YES。
requiresConstraintBasedLayout 自定义view应该重写这个方法返回YES,如果它不能使用autoresing正确布局。
在自定义视图中,你能完全控制它子视图的布局。你可以增加本地约束;根据内容变化需要,你可以改变本地约束;你可以为子视图调整布局操作的结果;或者你可以选择抛弃自动布局。
但确保你明智的使用这个权利。大多数情况下可以简单地通过为你的子视图简单的增加本地约束来处理。
本地约束
如果我们想用几个子视图组成一个自定义视图,我们需要以某种方式布局这些子视图。在自动布局的环境中,自然会想到为这些视图增加本地约束。然而,需要注意的是,这将会使你自定义的视图是基于自动布局的,这个视图不能再被使用于未启用自动布局的 windows 中。最好通过实现 requiresConstraintBasedLayout
返回 YES 明确这个依赖。
添加本地约束的地方是 updateConstraints
。确保在你的实现中增加任何你需要布局子视图的约束条件之后,调用一下 [super updateConstraints]
。在这个方法中,你不会被允许禁用何约束条件,因为你已经进入上面所描述的布局过程的第一步了
如果尝试着这样做,将会产生一个友好的错误信息 “programming error”。 如果稍后一个失效的约束条件发生了改变的话,你需要立刻移除这个约束并调用 setNeedsUpdateConstraints
。事实上,仅在这种情况下你需要触发更新约束条件的操作。
控制子视图布局
如果你不能利用布局约束条件达到子视图预期的布局,你可以进一步在 iOS 里重写 layoutSubviews
或者在 OS X 里面重写layout
。通过这种方式,当约束条件系统得到解决并且结果将要被应用到视图中时,你便已经进入到布局过程的第二步。layoutSubviews / layout
。这就意味着你在这个视图里的视图树里抛弃了自动布局。从现在起,你可以按喜欢的方式手动放置子视图。[super layoutSubviews]
/ [super layout]
,然后对布局进行微调。你可以通过这种方式创建那些通过定于约束无法实现的布,比如,由到视图大小之间的关系或是视图之间间距的关系来定义的布局。
这方面另一个有趣的使用案例就是创建一个布局依赖的视图树。当自动布局完成第一次传递并且为自定义视图的子视图设置好 frame 后,你便可以检查子视图的位置和大小,并为视图层级和(或)约束条件做出调整。WWDC session 228 – Best Practices for Mastering Auto Layout 有一个很好的例子。
你也可以在第一次布局操作完成后再决定改变约束条件。比如,如果视图变得太窄的话,将原来排成一行的子视图转变成两行。
- layoutSubviews
{
[super layoutSubviews];
if (self.subviews[0].frame.size.width <= MINIMUM_WIDTH)
{
[self removeSubviewConstraints];
self.layoutRows += 1; [super layoutSubviews];
}
}
- updateConstraints
{
// 根据 self.layoutRows 添加约束...
[super updateConstraints];
}
• requiresConstraintBasedLayout
• updateConstraints
• alignmentRectForFrame:, frameForAlignmentRect:
• sizeThatFits:
• layoutSubviews
• didAddSubview: , willRemoveSubview:
• willMoveToSuperview:, didMoveToSuperview
• willMoveToWindow:,didMoveToWindow