I have a series of (say) boxes on the screen in a row, all subviews of my main view. Each is a UIView. I want to shift them all left and have a new view also enter the screen from the right in lockstep. Here's what I'm doing:
// First add a dummy view offscreen
UIView * stagingView = /* make this view, which sets up its width/height */
CGRect frame = [stagingView frame];
frame.origin.x = /* just off the right side of the screen */;
[stagingView setFrame:frame];
[self addSubview:stagingView];
And then I set up animations in one block for all of my subviews (which includes the one I just added):
[UIView beginAnimations:@"shiftLeft" context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(_animationDidStop:context:)];
[UIView setAnimationDuration:0.3];
for (UIView * view in [self subviews]) {
CGRect frame = [view frame];
frame.origin.x -= (frame.size.width + viewPadding);
[view setFrame:frame];
}
[UIView commitAnimations];
Here's what I expect: The (three) views already on screen get shifted left and the newly staged view marches in from the right at the same time.
Here's what happens: The newly staged view animates in exactly as expected, and the views already on the screen do not appear to move at all! (Or possibly they jump without animation to their end locations).
And! If I comment out the whole business of creating the new subview offscreen... the ones onscreen do animate correctly!
Huh?
UPDATE: After some more poking around, I found something amazing: I can fix the problem by making my custom subclass of layoutSubviews
return without doing any work if it's called between the time the animation is set up, and the time it completes. That method needs to be doing some work to tweak the position of these subviews during orientation changes. But I don't really understand the interplay of the animations with this method-- I would think it would get called eventually perhaps at the end, which would make sense and which should essentially be a no-op after the animation. Can anyone explain the interaction to me? It seems like I'm close to enlightenment but not quite there yet. Thanks!
frame.origin.x
declaration should be! :) But seriously, that last line in the add-view block: is that supposed to be[self stagingView];
, or are you missing something (like a call toaddSubview:
)? – TimaddSubview:
that got mangled in my copy/paste/edit-for-clarity. – Ben Zotto