16

我有UIView一堆子视图,全部使用layoutSubviews. 调整大小时view,相对位置都会发生变化。我希望在动画调整大小(使用 +[UIView beginAnimations:]调用)期间进行这些重新计算。这似乎没有发生。有任何想法吗?

4

4 回答 4

26

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

这对于单个“标准” 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。

于 2010-09-12T03:48:03.280 回答
14

我知道这是一个老问题,但这段代码对我来说非常有效(适合你改变框架的例子)。

-(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。很好地解释了“层树”,您只需强制表示层显示带有动画的模型层的最后阶段。

这种方法的优点是可以控制帧/边界变化何时被动画化以及何时是即时的。

希望这可以帮助某人:)。

于 2012-09-05T16:33:39.927 回答
14

完成@GrizzlyNetch的回答,你可以设置UIViewAnimationOptionLayoutSubviews动画选项,所以你不需要调用layoutIfNeeded

-(void)someMethod{
    double duration = ...;
    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        self.frame = ...;
    } completion:nil];
}
于 2014-09-25T01:09:42.740 回答
5

发布以确保完整性。感谢 tc。用于解释我想要做的事情,确切地说,Core Animation 不支持。

我最终想出了一个合理的解决方案。与其在 -layoutSubviews 中布局我的子视图,不如在 -setBounds: 中布局。然后,当我在 UIView +beginAnimations: 块中包装 -setBounds: 调用时,这些定位调用也是动画的,最终结果是一切都正确地动画到它应该上帝的位置。

于 2010-09-12T13:39:13.093 回答