Restore pre-iOS7 UINavigationController pushViewController animation

前端 未结 10 2114
终归单人心
终归单人心 2020-11-30 21:14

So. Just started transitioning my IOS code to IOS7, and ran into a bit of problem.

I\'ve got a UINavigationController, which has child ViewControllers a

相关标签:
10条回答
  • 2020-11-30 21:52

    Thanks guys for the feedback. Found a solution in completely recreating the UINavigationController's behavior. When I was nearly finished I ran into Nick Lockwood's solution:

    https://github.com/nicklockwood/OSNavigationController

    OSNavigationController is a open source re-implementation of UINavigationController. It currently features only a subset of the functionality of UINavigationController, but the long-term aim is to replicate 100% of the features.

    OSNavigationController is not really intended to be used as-is. The idea is that you can fork it and then easily customize its appearance and behaviour to suit any special requirements that your app may have. Customizing OSNavigationController is much simpler than trying to customize UINavigationController due to the fact that the code is open and you don't need to worry about private methods, undocumented behavior, or implementation changes between versions.

    By overriding my UINavigationController with his code, I was able to work with background images in UINavigationcontrollers

    Thanks!

    0 讨论(0)
  • 2020-11-30 21:54

    I had a problem where when UIViewController A did a pushViewController to push UIViewController B, the push animation would stop at about 25%, halt, and then slide B in the rest of the way.

    This DID NOT happen on iOS 6, but as soon as I started using iOS 7 as the base SDK in XCode 5, this started happening.

    The fix is that view controller B did not have a backgroundColor set on its root view (the root view is the one that is the value of viewController.view, that you typically set in loadView). Setting a backgroundColor in that root view's initializer fixed the problem.

    I managed to fix this as follows:

    // CASE 1: The root view for a UIViewController subclass that had a halting animation
    
    - (id)initWithFrame:(CGRect)frame
    
    {
    
         if ((self = [super initWithFrame:frame])) {
    
              // Do some initialization ...
    
              // self.backgroundColor was NOT being set
    
              // and animation in pushViewController was slow and stopped at 25% and paused
    
         }
    
         return self;
    
    }
    
    // CASE 2: HERE IS THE FIX
    
    - (id)initWithFrame:(CGRect)frame
    
    {
    
         if ((self = [super initWithFrame:frame])) {
    
              // Do some initialization ...
    
              // Set self.backgroundColor for the fix!
    
              // and animation in pushViewController is no longer slow and and no longer stopped at 25% and paused
    
              self.backgroundColor = [UIColor whiteColor]; // or some other non-clear color
    
         }
    
         return self;
    
    }
    
    0 讨论(0)
  • 2020-11-30 21:55

    I managed to workaround the new transition type by creating a category for UINavigationController. In my case I needed to revert it to the old transition style because I have transparent viewControllers that slide over a static background.

    • UINavigationController+Retro.h

      @interface UINavigationController (Retro)
      
      - (void)pushViewControllerRetro:(UIViewController *)viewController;
      - (void)popViewControllerRetro;
      
      @end
      
    • UINavigationController+Retro.m

      #import "UINavigationController+Retro.h"
      
      @implementation UINavigationController (Retro)
      
      - (void)pushViewControllerRetro:(UIViewController *)viewController {
          CATransition *transition = [CATransition animation];
          transition.duration = 0.25;
          transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
          transition.type = kCATransitionPush;
          transition.subtype = kCATransitionFromRight;
          [self.view.layer addAnimation:transition forKey:nil];
      
          [self pushViewController:viewController animated:NO];
      }
      
      - (void)popViewControllerRetro {
          CATransition *transition = [CATransition animation];
          transition.duration = 0.25;
          transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
          transition.type = kCATransitionPush;
          transition.subtype = kCATransitionFromLeft;
          [self.view.layer addAnimation:transition forKey:nil];
      
          [self popViewControllerAnimated:NO];
      }
      
      @end
      
    0 讨论(0)
  • 2020-11-30 21:56

    Found another great resource to help out:

    http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions

    Using iOS7 TLTransitionAnimator to create custom animations

    0 讨论(0)
  • 2020-11-30 22:06

    Apparently in iOS7 there's a new way define your own custom UIViewController transitions. Look in the docs for UIViewControllerTransitioningDelegate. Also, here's a link to an article about it: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

    0 讨论(0)
  • 2020-11-30 22:08

    I voted for @Arne's answer, because I find it the most elegant solution to this problem. I would just like to add some code in order to answer to @Bill's problem from his comment on @Arne's solution. Here's comment quote:

    Thanks, this works for me. However, when the user taps the Back button, it reverts to the busted animation (because the back button doesn't call popViewControllerRetro). – Bill Oct 3 at 12:36

    In order to call popViewControllerRetro when back button is pressed, there's a small hack you can perform in order to achieve this. Go into your pushed view controller, import UIViewController+Retro.h and add this code in your viewWillDisappear method:

    - (void)viewWillDisappear:(BOOL)animated {
        if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
            [self.navigationController popViewControllerRetro];
        }
    
        [super viewWillDisappear:animated];
    }
    

    This if statement will detect when Back button is pressed and will call popViewControllerRetro from category class.

    Best regards.

    0 讨论(0)
提交回复
热议问题