iOS 7的手勢滑動返回功能

來源:互聯網
上載者:User

標籤:

  現在使用預設範本建立的iOS App都支援手勢返回功能,如果導覽列的返回按鈕是自訂的那麼則會失效,也可以參考這裏手動設定無效。

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {      self.navigationController.interactivePopGestureRecognizer.enabled = NO;  }  

  如果是因為自訂導覽按鈕而導致手勢返回失效,那麼可以在NavigationController的viewDidLoad函數中添加如下代碼:

- (void)viewDidLoad  {      [super viewDidLoad];      // Do any additional setup after loading the view.            __weak typeof (self) weakSelf = self;      if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {          self.interactivePopGestureRecognizer.delegate = weakSelf;      }  }  

  這樣寫了以後就可以通過手勢滑動返回上一層了,但是如果在push過程中觸發手勢滑動返回,會導致導覽列崩潰(從日誌中可以看出)。針對這個問題,我們需要在pop過程禁用手勢滑動返回功能,需要實現協議“UINavigationControllerDelegate”

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated  {        // fix ‘nested pop animation can result in corrupted navigation bar‘      if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {          self.interactivePopGestureRecognizer.enabled = NO;      }            [super pushViewController:viewController animated:animated];  } - (void)navigationController:(UINavigationController *)navigationController         didShowViewController:(UIViewController *)viewController                      animated:(BOOL)animated  {      if ([navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {          navigationController.interactivePopGestureRecognizer.enabled = YES;      }  }  

  除了使用系統預設的動畫,還可以使用自訂過渡動畫(豐滿的文檔):

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController                                    animationControllerForOperation:(UINavigationControllerOperation)operation                                                 fromViewController:(UIViewController *)fromVC                                                   toViewController:(UIViewController *)toVC  {      if (operation == UINavigationControllerOperationPop) {          if (self.popAnimator == nil) {              self.popAnimator = [WQPopAnimator new];          }          return self.popAnimator;      }            return nil;  }    - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController                           interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController  {      return self.popInteractionController;  }    #pragma mark -     - (void)enablePanToPopForNavigationController:(UINavigationController *)navigationController  {      UIScreenEdgePanGestureRecognizer *left2rightSwipe = [[UIScreenEdgePanGestureRecognizer alloc]                                                           initWithTarget:self                                                           action:@selector(didPanToPop:)];      //[left2rightSwipe setDelegate:self];      [left2rightSwipe setEdges:UIRectEdgeLeft];      [navigationController.view addGestureRecognizer:left2rightSwipe];            self.popAnimator = [WQPopAnimator new];      self.supportPan2Pop = YES;  }    - (void)didPanToPop:(UIPanGestureRecognizer *)panGesture  {      if (!self.supportPan2Pop) return ;            UIView *view = self.navigationController.view;            if (panGesture.state == UIGestureRecognizerStateBegan) {          self.popInteractionController = [UIPercentDrivenInteractiveTransition new];          [self.navigationController popViewControllerAnimated:YES];      } else if (panGesture.state == UIGestureRecognizerStateChanged) {          CGPoint translation = [panGesture translationInView:view];          CGFloat d = fabs(translation.x / CGRectGetWidth(view.bounds));          [self.popInteractionController updateInteractiveTransition:d];      } else if (panGesture.state == UIGestureRecognizerStateEnded) {          if ([panGesture velocityInView:view].x > 0) {              [self.popInteractionController finishInteractiveTransition];          } else {              [self.popInteractionController cancelInteractiveTransition];          }          self.popInteractionController = nil;      }  }  

  如下這個代理方法是用來提供一個非互動過渡動畫的:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController                                    animationControllerForOperation:(UINavigationControllerOperation)operation                                                 fromViewController:(UIViewController *)fromVC                                                   toViewController:(UIViewController *)toVC  {      if (operation == UINavigationControllerOperationPop) {          if (self.popAnimator == nil) {              self.popAnimator = [WQPopAnimator new];          }          return self.popAnimator;      }            return nil;  }  

  而下面這個代理方法則是提供互動式動畫:

- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController                           interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController  {      return self.popInteractionController;  }  

  這兩個組合起來使用。首先,我們需要有個動畫:

@interface WQPopAnimator : NSObject <UIViewControllerAnimatedTransitioning>    @end  

  

#import "WQPopAnimator.h"    @implementation WQPopAnimator    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext  {      return 0.4;  }    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext  {      UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];      UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];      [[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view];            __block CGRect toRect = toViewController.view.frame;      CGFloat originX = toRect.origin.x;      toRect.origin.x -= toRect.size.width / 3;      toViewController.view.frame = toRect;            [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{          CGRect fromRect = fromViewController.view.frame;          fromRect.origin.x += fromRect.size.width;          fromViewController.view.frame = fromRect;                    toRect.origin.x = originX;          toViewController.view.frame = toRect;      } completion:^(BOOL finished) {          [transitionContext completeTransition:![transitionContext transitionWasCancelled]];      }];  }    @end  

  其次,互動式動畫是通過

UIPercentDrivenInteractiveTransition

  來維護的,在滑動過程中根據滑動距離來進行更新:

} else if (panGesture.state == UIGestureRecognizerStateChanged) {          CGPoint translation = [panGesture translationInView:view];          CGFloat d = fabs(translation.x / CGRectGetWidth(view.bounds));          [self.popInteractionController updateInteractiveTransition:d];  

  當手勢結束時要做出收尾動作:

} else if (panGesture.state == UIGestureRecognizerStateEnded) {          if ([panGesture velocityInView:view].x > 0) {              [self.popInteractionController finishInteractiveTransition];          } else {              [self.popInteractionController cancelInteractiveTransition];          }          self.popInteractionController = nil;      }  

  同樣地,自訂的動畫也會有上面提到的導覽列崩潰問題,也可以通過類似的方法來解決:

- (void)navigationController:(UINavigationController *)navigationController         didShowViewController:(UIViewController *)viewController                      animated:(BOOL)animated  {      if (viewController == self.navigationController.pushingViewController) {          self.supportPan2Pop = YES;          self.navigationController.pushingViewController = nil;      }  

  補充:位於當前navgationController的第一個([0])viewController時需要設定手勢代理,不響應。

 

原文地址:http://blog.csdn.net/jasonblog/article/details/28282147

  

iOS 7的手勢滑動返回功能

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.