Tar*_*rfa 105 iphone xcode uiview
谁能给上之间的关系明确的解释UIView's
setNeedsLayout
,layoutIfNeeded
和layoutSubviews
方法呢?以及将使用所有三个的示例实现.谢谢.
让我感到困惑的是,如果我向自定义视图发送一条setNeedsLayout
消息,它会在此方法之后调用它layoutSubviews
,然后跳过它layoutIfNeeded
.从文档我预计流量为setNeedsLayout
>导致layoutIfNeeded
被称为>使layoutSubviews
被调用.
n8g*_*ray 103
我仍然试图自己解决这个问题,所以请怀疑一点,如果它包含错误,请原谅我.
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.
}
Run Code Online (Sandbox Code Playgroud)
AFAIK layoutIfNeeded
通常不会在子类中被覆盖.这是你注定当你想要一个视图进行布局调用一个方法现在.Apple的实现可能如下所示:
-(void)layoutIfNeeded {
if (self._needsLayout) {
UIView *sv = self.superview;
if (sv._needsLayout) {
[sv layoutIfNeeded];
} else {
[self layoutSubviews];
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以调用layoutIfNeeded
一个视图来强制它(以及必要时的超级视图)立即布局.
que*_*dam 34
我想补充一下n8gray的答案,在某些情况下你需要打电话setNeedsLayout
跟随layoutIfNeeded
.
例如,假设您编写了一个扩展UIView的自定义视图,其中子视图的定位很复杂,无法使用autoresizingMask或iOS6 AutoLayout完成.可以通过覆盖来完成自定义定位layoutSubviews
.
例如,假设您有一个自定义视图,该视图具有contentView
属性和edgeInsets
属性,允许设置contentView周围的边距.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);
}
Run Code Online (Sandbox Code Playgroud)
如果您希望能够在更改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
}
Run Code Online (Sandbox Code Playgroud)
这样,如果执行以下操作,如果更改动画块内的edgeInsets属性,则将动画化contentView的帧更改.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Run Code Online (Sandbox Code Playgroud)
如果您没有在setEdgeInsets方法中添加对layoutIfNeeded的调用,则动画将无法工作,因为layoutSubviews将在下一个更新周期调用,这相当于在动画块之外调用它.
如果您只在setEdgeInsets方法中调用layoutIfNeeded,则不会发生任何事情,因为未设置setNeedsLayout标志.
归档时间: |
|
查看次数: |
45150 次 |
最近记录: |