我有一个自定义视图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
而不会产生负面影响?
以下是我考虑的一些可能的答案,以及为什么它们对我来说似乎不太满意:
在使用CustomView
的任何视图控制器中,将animate
的呼叫推迟到viewDidLayoutSubviews
。
这会强制对使用此视图的视图控制器进行笨拙的限制。
在CustomView
的{{1}}方法中,首先调用layoutSubviews
,然后重新启动动画,如果它已在运行。
一个有趣的想法,但[super layoutSubviews]
有多个级别的子视图。因此,即使在CustomView
之后,视图层次结构中的许多视图仍然没有有效的框架,这意味着[super layoutSubviews]
仍会出现行为异常。
在animate
的{{1}}方法中,首先调用CustomView
,然后在最终重新启动动画之前,使用layoutSubviews
手动布局任何所需视图的帧它已经在运行。
这可能确实有效,但似乎不是一个好主意。我想尽可能地将布局工作留给自动布局。
答案 0 :(得分:0)
为什么不跳过不感兴趣的案子?
- (void)animate {
if (CGRectEqualToRect(self.frame, CGRectZero) return;
// ...animate.
}