Search code examples
objective-canimationuiviewuiviewanimationtransition

UIView transitionFromView:toView: isn't animating


I'm trying to animate a transition for one specific subView among many. Originally, when I tried to perform the transitionFromView:toView: it animated the entire superView, which is not what I want. I only want the specific subViews to animate. So I searched and found this: Transition behavior using transitionFromView and transitionWithView, which suggests creating a container view to perform the animations in. Ok, easy enough, so I came up with this code:

UIView *container = [[UIView alloc] init];
container.frame = selected.frame;
selected.frame = container.bounds;
[selected.superview addSubview:container];
[container addSubview:selected];
[UIView transitionFromView:selected toView:normal duration:.2f options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL fin){
    normal.frame = container.frame;
    [container.superview addSubview:normal];
    [container removeFromSuperview];
}];

But now I get no animation at all. I'm probably missing something simple but I can't find it. Any ideas?

UPDATE

All of the values are initialized. If I break just before this code block runs I pull this up through the debugger console:

(gdb) po normal
<SLabel: 0x9c43150; frame = (0 0; 40 40); text = '28'; tag = 28; layer = <CALayer: 0x9c43190>>
(gdb) po selected
<SLabel: 0x9ca5f00; frame = (137 148; 45 37); text = '28'; tag = 28; layer = <CALayer: 0x9c596b0>>
(gdb) po [normal superview]
Can't print the description of a NIL object.
(gdb) po [selected superview]
<UIView: 0x9c4c890; frame = (0 0; 320 190); layer = <CALayer: 0x9c4c8c0>>

After the code has run through line 5 (just before the transition method) I get:

(gdb) po container
<UIView: 0x848bfc0; frame = (47 74; 45 37); layer = <CALayer: 0x9c32b10>>
(gdb) po [container superview]
<UIView: 0x9c4c890; frame = (0 0; 320 190); layer = <CALayer: 0x9c4c8c0>>
(gdb) po [selected superview]
<UIView: 0x848bfc0; frame = (47 74; 45 37); layer = <CALayer: 0x9c32b10>>

So everything seems correct. The container is placed at the location of the selected view (which is the view I want to flip from). The container added to the selected view's superview. The selected view is placed inside the container. And finally the transition is run (with cleanup afterward). But I still get no animation...the transition occurs immediately.

Please note that the transition between the view is occurring correctly. I'm just getting no animation at all.

Another question: Do the transitioning views HAVE to be a subview, no matter how distant, of a UINavigationController view in order to perform the animation? I've never seen any requirement like this that I can remember, but it's the one non-standard aspect of my code. If you follow the superview's of each view, not one will be part of a nav controller before it hits the window. Sometimes Apple's frameworks depend on each other in unexpected ways...I was wondering if this was one of them.

The final answer was that all my code was correct. What was happening is layoutSubviews was being called after I started the animation, which was re-laying out all my subviews before the animation even had a chance to start. I'm not quite sure why it was called. I didn't call it from my code, so for some reason my moving views around was triggering UIView to call it I guess. At any rate, I moved my code out of layoutSubviews into a private method and only call it when the size of the view changes. Everything works now. :)


Solution

  • The code you put there does not have error, the only thing I can think is that you have some problem in other place. You are sure that your container view is going to your view that is showed?

    In what method you are calling it?

    Because to do the animation what you need to do is showed bellow (and from your code you post here you are doing it):

    UIView* normalView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    [normalView setBackgroundColor:[UIColor redColor]];
    UIView* selectedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    [selectedView setBackgroundColor:[UIColor blueColor]];
    
    UIView* container = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    [container setBackgroundColor:[UIColor grayColor]];
    
    [container addSubview:selectedView];
    [self.view addSubview:container];
    

    And then call the method to do the flip.

    [UIView transitionFromView:selectedView toView:normalView duration:2.0 options:UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL fin){}];