0

I would like to custom push and pop a view controller use pull down/up animation like this:

enter image description here

I try to change the y position but it doesn't work (it doesn't show up animation at all).

  [self.navigationController pushViewController:nextController animated:NO];

  self.view.frame = CGRectMake(self.view.frame.origin.x,   self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
  [UIView animateWithDuration:0.6 animations:^{
   self.view.frame = CGRectMake(0, -self.view.frame.size.height, self.view.frame.size.width, self.view.frame.size.height);
} completion:nil];

Is there any suggestion?
P/s: I have to use push view controller in this case instead of presentViewController

Update:
I try to use UINavigationControllerDelegate like this:
PropertyViewController.h

@interface PropertyViewController : UIViewController <UINavigationControllerDelegate>{

}

PropertyViewController.m

 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
  NSLog(@"willShowViewController");
}
 - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
NSLog(@"didShowViewController");
}

 -(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
  
  // THIS METHOD IS NOT CALLED AT ALL
  NSLog(@"animationControllerForOperation");
  TLTransitionAnimator *animator = [TLTransitionAnimator new];
  animator.presenting = (operation == UINavigationControllerOperationPush);
   animator.duration = 0.5;
   return animator;
 }

 - (void)viewGallery{
   // PUSH VIEW CONTROLLER
   GalleryViewController* galleryController = [[GalleryViewController alloc] initWithNibName:@"GalleryViewController" bundle:nil]; 
   galleryController.navigationController.delegate = self; 
   [self.navigationController pushViewController:galleryController animated:YES];
 }

Update 2:
After fix the problem method not called with this line in PropertyViewController.m

  self.navigationController.delegate = self;

I face with another problem.
The slide down animation on push does work, but the slide up doesn't .
Here is my custom animation:

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

[[transitionContext containerView] addSubview:toViewController.view];
if (self.presenting) { // push
    fromViewController.view.transform = CGAffineTransformIdentity;
    toViewController.view.transform = CGAffineTransformMakeTranslation(0, toViewController.view.frame.size.height);
}else{ // pop
    fromViewController.view.transform = CGAffineTransformMakeTranslation(0, fromViewController.view.frame.size.height);
}

[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
    if (self.presenting) { // push
        fromViewController.view.transform = CGAffineTransformMakeTranslation(0, toViewController.view.frame.size.height);
        toViewController.view.transform = CGAffineTransformMakeTranslation(0, toViewController.view.frame.size.height);
    } else { // pop
        fromViewController.view.transform = CGAffineTransformMakeTranslation(0, 0);
    }
} completion:^(BOOL finished) {
    toViewController.view.transform = CGAffineTransformIdentity;
    
    [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}

The problem 2:
The pull down animation only works on the first time, from the second times, layout renders wrong, I have no idea why this can happen.

Where am I wrong here?

Community
  • 1
  • 1
ductran
  • 10,043
  • 19
  • 82
  • 165

2 Answers2

4

You should Implement UIViewControllerAnimatedTransitioning.

  1. Make your FromViewController.m conform to UINavigationControllerDelegate. Other sample code out there tells you to conform to UIViewControllerTransitioningDelegate, but that's only if you're presenting the ToViewController.

    @interface ViewController : UIViewController <UINavigationControllerDelegate>
    
  2. Return your custom transition animator object in the delegate callback method in FromViewController:

    - (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC {
        TransitionAnimator *animator = [TransitionAnimator new];
        animator.presenting = (operation == UINavigationControllerOperationPush);
        return animator;
    }
    
  3. Create your custom TransitionAnimator animator class and paste these sample methods:

    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
        return 0.5f;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        [[transitionContext containerView] addSubview:toViewController.view];
    
        if (self.presenting) {
            toViewController.view.transform = CGAffineTransformMakeTranslation(0, toViewController.view.frame.size.height);
        }
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            if (self.presenting) {
                toViewController.view.transform = CGAffineTransformIdentity;
            } else {
                fromViewController.view.transform = CGAffineTransformMakeTranslation(0, toViewController.view.frame.size.height);
            }
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        }];
    
    }
    

Most of the implementation is from here, I just edited the transition method to your needs: https://stackoverflow.com/a/25026102/2242359

I still strongly recommend to go over some or all these guides:
http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions/
http://www.objc.io/issue-5/view-controller-transitions.html
http://objectivetoast.com/2014/03/17/custom-transitions-on-ios/

Community
  • 1
  • 1
Aviel Gross
  • 9,770
  • 3
  • 52
  • 62
  • Thanks,I use xib file to load viewcontroller and I have to use push view controller instead of `presentViewController` so I don't know how to apply UIViewControllerAnimatedTransitioning in this case. Could you explain more detail? – ductran Apr 07 '15 at 17:37
  • I updated my question. The problem is that method `navigationController: animationControllerForOperation` is not called. And I don't know where is my problem. – ductran Apr 08 '15 at 03:48
  • When pushing your `GalleryViewController` you should set `self.navigationController.delegate = self;` instead `galleryController.navigationController.delegate = self;` – Aviel Gross Apr 08 '15 at 05:33
  • Thanks, my mistake, this method does work now. I just updated my question. I need to change a little things with your answer to make push animation works, but the pop animation (pull up from gallery) still doesn't effect (nothing happens when pop view controller). Do you have any suggestion? – ductran Apr 08 '15 at 06:11
2

Try this :

UIViewController *yourViewController = [[UIViewController alloc]init];

[UIView  beginAnimations: @"Showinfo"context: nil];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController: yourViewController animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
saraman
  • 568
  • 7
  • 19