基于尚未确定的布局动画UIView

时间:2015-03-11 18:19:09

标签: ios animation uiview autolayout

我有一个自定义视图CustomView,可以根据animate消息设置自己的动画:

// in a view controller
[self.customView animate];

-[CustomView animate]内,逻辑如下:

- (void)animate {
    for each subview {
        startFrame = subview.frame;
        endFrame = EndFrameFromStartFrame(startFrame);
        subview.animation = AnimationLoopBetween(startFrame, endFrame);
    }
}

*此块为伪代码。

也就是说,animate方法检查每个子视图的当前帧并为每个子视图生成动画结束帧,该子视图本质上是一个大于当前帧的固定比率的帧。然后,它为每个子视图创建一个动画,该动画会改变其子视图的帧,在当前(或开始)帧和结束帧之间交替变换。

这种方法通常效果很好。它允许CustomView正确地设置动画,无论其超级视图的位置和大小如何。

但是,在少数情况下,CustomView的“用户”(即视图控制器)在其生命周期的早期就会调用animate - 事实上,这么早,Auto Layout还没有做了任何约束或布局通过。这意味着当animate的所有子视图帧都为CustomView时,系统会调用CGRectZero。正如您可能猜到的那样,这会导致动画的起始值和结束值都被错误地计算出来。

即使在布局传递完成后,并且视图的模型图层具有正确的帧,CustomView实例仍然不可见,因为它的子视图很乐意从一个零矩形动画到另一个零矩阵。不好。

我应该如何重组此动画行为,以允许此类用户随时调用animate而不会产生负面影响?


以下是我考虑的一些可能的答案,以及为什么它们对我来说似乎不太满意:

  1. 在使用CustomView的任何视图控制器中,将animate的呼叫推迟到viewDidLayoutSubviews
    这会强制对使用此视图的视图控制器进行笨拙的限制。

  2. CustomView的{​​{1}}方法中,首先调用layoutSubviews,然后重新启动动画,如果它已在运行。
    一个有趣的想法,但[super layoutSubviews]有多个级别的子视图。因此,即使在CustomView之后,视图层次结构中的许多视图仍然没有有效的框架,这意味着[super layoutSubviews]仍会出现行为异常。

  3. animate的{​​{1}}方法中,首先调用CustomView,然后在最终重新启动动画之前,使用layoutSubviews手动布局任何所需视图的帧它已经在运行。
    这可能确实有效,但似乎不是一个好主意。我想尽可能地将布局工作留给自动布局。

1 个答案:

答案 0 :(得分:0)

为什么不跳过不感兴趣的案子?

- (void)animate {
  if (CGRectEqualToRect(self.frame, CGRectZero) return;
  // ...animate.
}