在约束依赖于框架的自定义视图中使用自动布局
我正在编写一个自定义视图,以编程方式初始化。 我重写updateConstraints
以添加此视图所需的所有约束。 :
- (void)updateConstraints { [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1 constant:0]]; [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeBottom multiplier:1 constant:0]]; // some more constraints, you get the point self.bottomSpacingConstraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-(0.2 * CGRectGetHeight(self.bounds))]; [self addConstraint:self.bottomSpacingConstraint]; [super updateConstraints]; }
问题是self.bounds
返回CGRectZero
的等价物。 我做了我的研究,根据这objc.io文章 ,这是预期的框架不会被设置,直到layoutSubviews
被调用。 它也提到
要强制系统立即更新视图树的布局,可以调用
layoutIfNeeded
/layoutSubtreeIfNeeded
(分别在iOS和OS X上)。 如果您的后续步骤依赖最新的视图框架,这可能会有所帮助。
但是,当我补充
[self setNeedsLayout]; [self layoutIfNeeded];
在updateConstraints
设置self.bottomSpacingConstraint
之前,我仍然得到一个CGRectZero
框架。 根据objc.io文章(和这个答案 ),这些方法应该触发布局和更新框架。
任何人都可以点亮如何使这一切工作? 我对这个解决scheme感兴趣,并且解释了什么导致了哪些与布局相关的方法被调用(例如,在layoutSubviews
中改变现有约束的常量导致setNeedsUpdateConstraints
被调用,然后触发updateConstraints
并导致约束要多次添加)。
我敢肯定,你不能或不应该从updateConstraints
调用layoutIfNeeded
。 更新约束是在布局周期的早期部分,所以我不认为它会产生效果。
在你的情况下,解决scheme将检查layoutSubviews中的依赖于框架的约束的constant
属性,如果需要更新,请在那里更新它或调用setNeedsUpdateConstraints
(注意导致循环)。
你说更新约束触发器的另一个调用updateConstraints
– 这是真的,我认为你是滥用updateConstraints
– 它是基于您的视图的内容更改更新约束。 如果它们不存在,只应该添加这些约束。