我有UIView
一堆子视图,全部使用layoutSubviews
. 调整大小时view
,相对位置都会发生变化。我希望在动画调整大小(使用 +[UIView beginAnimations:]
调用)期间进行这些重新计算。这似乎没有发生。有任何想法吗?
4 回答
假设:您希望有多个动画步骤(即位置不随帧大小线性变化)。
这对于单个“标准” UIView 动画是不可能的。为什么?框架/边界只设置一次。
Core Animation有三个“层树”:
- 模型树是您的应用认为事物所在的位置。
- 演示树大约是屏幕上显示的内容。
- 渲染树大约是 Core Animation 正在合成的内容。
UIView 是模型层的(有点薄的)包装器。在 UIView 动画期间,Core Animation 会更新演示/渲染树——模型树代表动画的端点。结果是您的代码可以(在大多数情况下)将动画视为瞬时的——将视图从 A 移动到 B 会立即将其移动到 B;更改恰好对用户进行了动画处理。
你可以直接用 CALayer/CAAnimation 做更复杂的事情,但我没有研究这么多。
您可以使用 -[UIView setAnimationDidStopSelector:] 将多个动画链接在一起。(您也可以尝试将多个动画与 setAnimationDelay: 一起使用,但我不确定同一属性上的多个动画会发生什么情况;您可能会遇到 setAnimationBeginsFromCurrentState: 的运气。)
如果您想要真正细粒度的控制,CADisplayLink (OS 3.1+) 是一个在每次屏幕刷新后触发的计时器。一个备用选项(用于 3.0 支持)是在 30/60 Hz 左右使用 NSTimer。
我知道这是一个老问题,但这段代码对我来说非常有效(适合你改变框架的例子)。
-(void)layoutSubviews{
[super layoutSubviews];
// layout your subviews here, or whatever
}
-(void)someMethod{
double duration=...;
[UIView animateWithDuration:duration animations:^{
self.frame = ...;
[self layoutIfNeeded];
}];
}
当然,您可以从另一个对象调用此方法。“技巧”是调用 layoutIfNeeded (或直接调用 layoutSubviews - 同样的事情,如果您更改调用 setNeedsLayout 的框架)。
作为tc。很好地解释了“层树”,您只需强制表示层显示带有动画的模型层的最后阶段。
这种方法的优点是可以控制帧/边界变化何时被动画化以及何时是即时的。
希望这可以帮助某人:)。
完成@GrizzlyNetch的回答,你可以设置UIViewAnimationOptionLayoutSubviews
动画选项,所以你不需要调用layoutIfNeeded
:
-(void)someMethod{
double duration = ...;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
self.frame = ...;
} completion:nil];
}
发布以确保完整性。感谢 tc。用于解释我想要做的事情,确切地说,Core Animation 不支持。
我最终想出了一个合理的解决方案。与其在 -layoutSubviews 中布局我的子视图,不如在 -setBounds: 中布局。然后,当我在 UIView +beginAnimations: 块中包装 -setBounds: 调用时,这些定位调用也是动画的,最终结果是一切都正确地动画到它应该上帝的位置。