我在用:
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
这个单行代码的弹出导航视图,这是一个为我工作,但当我滑动屏幕中间屏幕这将不会像Instagram的iPhone应用程序.
这里我给一个Instagram应用程序的一个屏幕,你可以看到滑动右侧流行导航视图的示例:
解决方法
苹果说here:
interactivePopGestureRecognizer
The gesture recognizer responsible for popping the top view controller off the navigation stack. (read-only)
@property(nonatomic,readonly) UIGestureRecognizer *interactivePopGestureRecognizer
The navigation controller installs this gesture recognizer on its view
and uses it to pop the topmost view controller off the navigation
stack. You can use this property to retrieve the gesture recognizer
and tie it to the behavior of other gesture recognizers in your user
interface. When tying your gesture recognizers together,make sure
they recognize their gestures simultaneously to ensure that your
gesture recognizers are given a chance to handle the event.
所以你必须实现自己的UIGestureRecognizer,并将其行为绑定到UIViewController的interactivePopGestureRecognizer.
编辑:
这是我建立的一个解决方案.您可以实现符合UIViewControllerAnimatedTransitioning委托的自己的转换.该解决方案可以工作,但尚未经过彻底测试.
您将获得一个交互式滑动转换,以弹出ViewController.您可以从视图中的任何位置向右滑动.
已知问题:如果您启动平移并在视图宽度的一半之前停止,则转换将被取消(预期的行为).在此过程中,视图重置为其原始帧.他们是这个动画中的视觉故障.
示例的类别如下:
UINavigationController > ViewController > SecondViewController
CustomPopTransition.h:
#import <Foundation/Foundation.h> @interface CustomPopTransition : NSObject <UIViewControllerAnimatedTransitioning> @end
CustomPopTransition.m:
#import "CustomPopTransition.h" #import "SecondViewController.h" #import "ViewController.h" @implementation CustomPopTransition - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext { return 0.3; } - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { SecondViewController *fromViewController = (SecondViewController*)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; ViewController *toViewController = (ViewController*)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *containerView = [transitionContext containerView]; [containerView addSubview:toViewController.view]; [containerView bringSubviewToFront:fromViewController.view]; // Setup the initial view states toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController]; [UIView animateWithDuration:0.3 animations:^{ fromViewController.view.frame = CGRectMake(toViewController.view.frame.size.width,fromViewController.view.frame.origin.y,fromViewController.view.frame.size.width,fromViewController.view.frame.size.height); } completion:^(BOOL finished) { // Declare that we've finished [transitionContext completeTransition:!transitionContext.transitionWasCancelled]; }]; } @end
SecondViewController.h:
#import <UIKit/UIKit.h> @interface SecondViewController : UIViewController <UINavigationControllerDelegate> @end
SecondViewController.m:
#import "SecondViewController.h" #import "ViewController.h" #import "CustomPopTransition.h" @interface SecondViewController () @property (nonatomic,strong) UIPercentDrivenInteractiveTransition *interactivePopTransition; @end @implementation SecondViewController - (void)viewDidLoad { [super viewDidLoad]; self.navigationController.delegate = self; UIPanGestureRecognizer *popRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePopRecognizer:)]; [self.view addGestureRecognizer:popRecognizer]; } -(void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; // Stop being the navigation controller's delegate if (self.navigationController.delegate == self) { self.navigationController.delegate = nil; } } - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { // Check if we're transitioning from this view controller to a DSLSecondViewController if (fromVC == self && [toVC isKindOfClass:[ViewController class]]) { return [[CustomPopTransition alloc] init]; } else { return nil; } } - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController { // Check if this is for our custom transition if ([animationController isKindOfClass:[CustomPopTransition class]]) { return self.interactivePopTransition; } else { return nil; } } - (void)handlePopRecognizer:(UIPanGestureRecognizer*)recognizer { // Calculate how far the user has dragged across the view CGFloat progress = [recognizer translationInView:self.view].x / (self.view.bounds.size.width * 1.0); progress = MIN(1.0,MAX(0.0,progress)); if (recognizer.state == UIGestureRecognizerStateBegan) { NSLog(@"began"); // Create a interactive transition and pop the view controller self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init]; [self.navigationController popViewControllerAnimated:YES]; } else if (recognizer.state == UIGestureRecognizerStateChanged) { NSLog(@"changed"); // Update the interactive transition's progress [self.interactivePopTransition updateInteractiveTransition:progress]; } else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) { NSLog(@"ended/cancelled"); // Finish or cancel the interactive transition if (progress > 0.5) { [self.interactivePopTransition finishInteractiveTransition]; } else { [self.interactivePopTransition cancelInteractiveTransition]; } self.interactivePopTransition = nil; } } @end