Question

I am trying to mimic UINavigationController's pushViewController using UIView animation but I have seem to run into an issue. I cannot animate the self.view.frame.

This is the code I am using but self.view just won't move!

    [self.view addSubview:myViewController.view];
    [myViewController.view setFrame:CGRectMake(320, 0, 320, 480)];    
    [UIView animateWithDuration:0.5 
                     animations:^{
                         [self.view setFrame:CGRectMake(-320, 0, 320, 480)];
                         [myViewController.view setFrame:CGRectMake(0, 0, 320, 480)];
                     }
                     completion:^(BOOL finished){
                         [view1.view removeFromSuperview];
                     }];

Thanks!

Was it helpful?

Solution

Consider where the views are just before the animations start:

  • self.view.frame is (I assume) 0,0,320,380
  • myViewController.view is a subview of self.view
  • myViewController.view.frame is 320,0,320,480 in self.view's coordinate system, so it's outside of its superview's frame (and off the right edge of the screen)

Now consider where the views are after the animations finish:

  • self.view.frame is -320,0,320,480
  • myViewController.view is still a subview of self.view
  • myViewController.view.frame is 0,0,320,480 in self.view's coordinate system, so it's fully inside its superview's frame, but its frame in screen coordinates is -320,0,320,480, so it is now entirely off the left edge of the screen

You need to make myViewController.view a sibling of self.view, not a subview. Try this:

// Calculate the initial frame of myViewController.view to be
// the same size as self.view, but off the right edge of self.view.
// I don't like hardcoding coordinates...
CGRect frame = self.view.frame;
frame.origin.x = CGRectGetMaxX(frame);
myViewController.view.frame = frame;
[self.view.superview addSubview:myViewController.view];
// Now slide the views over.
[UIView animationWithDuration:0.5 animations:^{
    CGRect frame = self.view.frame;
    myViewController.view.frame = frame;
    frame.origin.x -= frame.size.width;
    self.view.frame = frame;
} completion:^(BOOL done){
    [view1.view removeFromSuperview];
}];

OTHER TIPS

Can't tell if you have other problems related to the context of where this code is called. Looks like view1 is a UIViewController subclass. You should rename that, pretty confusing.

I did notice a problem with your frame manipulations. It looks like self is a container view controller, e.g. self.view contains the views being animated (view1.view and myViewController.view and shouldn't be animated itself. If that's correct your animation should be:

[self.view addSubview:myViewController.view];
[myViewController.view setFrame:CGRectMake(320, 0, 320, 480)];    
[UIView animateWithDuration:0.5 
                 animations:^{
                     [view1.view setFrame:CGRectMake(-320, 0, 320, 480)];
                     [myViewController.view setFrame:CGRectMake(0, 0, 320, 480)];
                 }
                 completion:^(BOOL finished){
                     [view1.view removeFromSuperview];
                 }];

As an aside, it seems strange that a view controller would animate itself out of it's superview. If self is a container view controller I would expect the logic to be there. See my answer to Animate change of view controllers without using navigation controller stack, subviews or modal controllers? for an example of how to implement a container view controller. It is trivial to modify my example there to do the slide in animation you want.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top