在动画期间layoutSubviews?

时间:2010-09-12 02:39:54

标签: iphone animation uiviewanimation layoutsubviews

我有UIView个子视图,所有子视图都使用layoutSubviews定位。调整view的大小后,相对位置都会发生变化。我希望在动画调整大小期间(使用+ [UIView beginAnimations:]调用)进行这些重新计算。这似乎没有发生。有什么想法吗?

4 个答案:

答案 0 :(得分:24)

假设:您希望有多个动画步骤(即位置不随帧大小线性变化)。

使用单个“标准”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。

答案 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:调用时,这些定位调用也会被动画化,最终结果就是所有正确动画到它应该上帝的地方。