谁能给上之间的关系明确的解释UIView's
setNeedsLayout
, layoutIfNeeded
和layoutSubviews
方法呢? 和示例实现所有三个将被使用。 谢谢。
是什么让我感到困惑的是,如果我把我的自定义查看setNeedsLayout
消息,它会调用后,这个方法是非常接下来的事情layoutSubviews
,跳绳就在layoutIfNeeded
。 从文档我预计流量将setNeedsLayout
>导致layoutIfNeeded
被称为>导致layoutSubviews
调用。
我还在试图弄清楚这一点我自己,所以如果它包含错误借此与一些怀疑和原谅。
setNeedsLayout
是一个简单的一个:它只是在标记为需要布局的UIView设置一个标志的地方。 这将迫使layoutSubviews
下一重绘发生之前要对视图调用。 请注意,在很多情况下,你不需要因为的显式调用, autoresizesSubviews
属性。 如果是这样的设置(它是通过默认),则任何改变视图的帧将导致视图布置其子视图。
layoutSubviews
是你做的所有有趣的事情的方法。 这相当于drawRect
的布局,如果你愿意。 一个简单的例子可能是:
-(void)layoutSubviews {
// Child's frame is always equal to our bounds inset by 8px
self.subview1.frame = CGRectInset(self.bounds, 8.0, 8.0);
// It seems likely that this is incorrect:
// [self.subview1 layoutSubviews];
// ... and this is correct:
[self.subview1 setNeedsLayout];
// but I don't claim to know definitively.
}
AFAIK layoutIfNeeded
一般不意味着在子类中被覆盖。 这是你注定当你想要一个观点是正确的,现在布局调用的方法。 苹果的实现可能是这个样子:
-(void)layoutIfNeeded {
if (self._needsLayout) {
UIView *sv = self.superview;
if (sv._needsLayout) {
[sv layoutIfNeeded];
} else {
[self layoutSubviews];
}
}
}
你会打电话layoutIfNeeded
上以迫使它(以及它的superviews必要)立即布置。
我想在n8gray的回答补充一点,在某些情况下,你需要调用setNeedsLayout
通过遵循layoutIfNeeded
。
比方说,比如你写扩展UIView的自定义视图,其子视图的定位是复杂的,不能用autoresizingMask或iOS6的自动版式来完成。 自定义定位可以通过重写来完成layoutSubviews
。
举个例子,假设你有,有一个自定义视图contentView
属性和edgeInsets
属性,允许设置围绕内容查看边距。 layoutSubviews
是这样的:
- (void) layoutSubviews {
self.contentView.frame = CGRectMake(
self.bounds.origin.x + self.edgeInsets.left,
self.bounds.origin.y + self.edgeInsets.top,
self.bounds.size.width - self.edgeInsets.left - self.edgeInsets.right,
self.bounds.size.height - self.edgeInsets.top - self.edgeInsets.bottom);
}
如果你希望能够随时更改动画帧变化edgeInsets
财产,你需要重写edgeInsets
setter方法如下,并呼吁setNeedsLayout
其次layoutIfNeeded
:
- (void) setEdgeInsets:(UIEdgeInsets)edgeInsets {
_edgeInsets = edgeInsets;
[self setNeedsLayout]; //Indicates that the view needs to be laid out
//at next update or at next call of layoutIfNeeded,
//whichever comes first
[self layoutIfNeeded]; //Calls layoutSubviews if flag is set
}
这样,如果你做到以下几点,如果你改变了动画块内的edgeInsets财产的内容查看的帧变化将动画。
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
如果不加调用layoutIfNeeded在setEdgeInsets方法,动画将无法工作,因为layoutSubviews将在下一个更新周期,这相当于调用它的动画块外调用。
如果你只叫layoutIfNeeded在setEdgeInsets方法,因为setNeedsLayout标志未设置会发生什么。
文章来源: What is the relationship between UIView's setNeedsLayout, layoutIfNeeded and layoutSubviews?