layoutSubviews during an animation?

Ben Gottlieb picture Ben Gottlieb · Sep 12, 2010 · Viewed 16.5k times · Source

I have a UIView with a bunch of subviews, all positioned using layoutSubviews. When the view is resized, the relative positions all change. I'd like these re-calculations to happen during an animated resize (using +[UIView beginAnimations:] calls). This doesn't seem to be happening. Any ideas?

Answer

tc. picture tc. · Sep 12, 2010

Assumption: You want to have multiple animation steps (i.e. position doesn't change linearly with frame size).

This isn't possible with a single "standard" UIView animations. Why? The frame/bounds is only set once.

Core Animation has three "layer trees":

  • The model tree is where your app thinks things are.
  • The presentation tree is approximately what's being displayed on screen.
  • The render tree is approximately what Core Animation is compositing.

UIView is a (somewhat thin) wrapper around the model layer. During a UIView animation, Core Animation updates the presentation/render tree — the model tree represents the endpoint of animations. The upshot is that your code can (for the most part) treat animations as instantaneous — moving a view from A to B instantly moves it to B; the change just happens to be animated to the user.

There are more complicated things you can do with CALayer/CAAnimation directly, but I haven't investigated this much.

You could chain multiple animations together using -[UIView setAnimationDidStopSelector:]. (You could also try using multiple animations together with setAnimationDelay:, but I'm not sure what happens with multiple animations on the same property; you might have luck with setAnimationBeginsFromCurrentState:.)

If you want really fine-grained control, CADisplayLink (OS 3.1+) is a timer that fires after each screen refresh. A fallback option (for 3.0 support) is to use an NSTimer at 30/60 Hz or so.