我有UIView
个子视图,所有子视图都使用layoutSubviews
定位。调整view
的大小后,相对位置都会发生变化。我希望在动画调整大小期间(使用+ [UIView beginAnimations:]
调用)进行这些重新计算。这似乎没有发生。有什么想法吗?
答案 0 :(得分:24)
假设:您希望有多个动画步骤(即位置不随帧大小线性变化)。
使用单个“标准”UIView动画无法实现这一点。为什么?帧/边界只设置一次。
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。
答案 1 :(得分:14)
完成@ GrizzlyNetch's anwer,您可以设置UIViewAnimationOptionLayoutSubviews
动画选项,这样您就不需要致电layoutIfNeeded
:
-(void)someMethod{
double duration = ...;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
self.frame = ...;
} completion:nil];
}
答案 2 :(得分:13)
我知道这是一个老问题,但这段代码对我很有用(适合你改变帧的例子)。
-(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。很好地解释了“图层树”,你只需强制表示层用动画显示模型图层的最后阶段。
这种方法的优势在于可以控制帧/边界变化的动画时间和瞬时变化。
希望这有助于某人:)。
答案 3 :(得分:5)
发布完整性。感谢tc。用于解释Core Animation不支持我想要做的事情。
我最终想出了一个合理的解决方案。而不是在-layoutSubviews中布置我的子视图,我在-setBounds中这样做:然后,当我在UIView + beginAnimations:块中包装一个-setBounds:调用时,这些定位调用也会被动画化,最终结果就是所有正确动画到它应该上帝的地方。