参考推荐文章http://www.cocoachina.com/ios/20150717/12600.html
首先创建一个导航控制器 并获取控制器的手势识别器->获取视图->在视图上添加新建的拖拽手势->最后实现监听
//获取手势识别器
UIGestureRecognizer *gesture = self.interactivePopGestureRecognizer;
//禁用
gesture.enabled = NO;
UIView *gestureView = gesture.view;
//添加手势
UIPanGestureRecognizer *popRecognizer = [[UIPanGestureRecognizer alloc] init];
popRecognizer.delegate = self;
popRecognizer.maximumNumberOfTouches = 1;
[gestureView addGestureRecognizer:popRecognizer];
//添加监听并在类内部实现监听方法
[popRecognizer addTarget:[[NavigationInteractiveTransition alloc] init] action:@selector(StartDragPop:)];
实现监听方法
- (void)StartDragPop:(UIPanGestureRecognizer *)recognizer {
// translationInView获取手指在当前视图的位置
CGFloat progress = [recognizer translationInView:recognizer.view].x / recognizer.view.bounds.size.width;
if (recognizer.state == UIGestureRecognizerStateBegan) {
// 告诉控制器开始执行pop的动画
[self.vc popViewControllerAnimated:YES];
}
else if (recognizer.state == UIGestureRecognizerStateChanged) {
//更新手势的完成进度
[self.interactivePopTransition updateInteractiveTransition:progress];
}
else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
//手势结束时如果进度大于一半,那么就完成pop操作否则变回原样。
if (progress > 0.5) {
[self.interactivePopTransition finishInteractiveTransition];
}else {
[self.interactivePopTransition cancelInteractiveTransition];
}
self.interactivePopTransition = nil;
}
}
要求监听者实现UINavigationControllerDelegate代理方法
//如果这里返回nil 则不会调用方法2
//方法返回自定义动画
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC {
//判断如果是pop操作
if (operation == UINavigationControllerOperationPop)
// 自定义Pop动画对象
return [[PopAnimation alloc] init];
return nil;
}
//返回动画进度
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
//如果是我们自定义的Pop动画对象,那么就返回interactivePopTransition来监控动画完成度。
if ([animationController isKindOfClass:[PopAnimation class]])
//这里需要提前创建interactivePopTransition
return self.interactivePopTransition;
return nil;
}
PopAnimation类要求实现UIViewControllerAnimatedTransitioning协议
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
//这个方法返回动画执行的时间
return 0.25;
}
//在这个方法中进行自定义动画
// transitionContext,用来获取一系列动画执行相关的对象。
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
// 获取动画来自的那个控制器
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// 获取转场到的那个控制器
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//获取容器视图
UIView *containerView = [transitionContext containerView];
self.containerView = containerView;
//将视图添加到容器视图
[containerView insertSubview:toViewController.view belowSubview:fromViewController.view];
NSTimeInterval duration = [self transitionDuration:transitionContext];
// 执行动画
[UIView animateWithDuration:duration animations:^{
fromViewController.view.transform = CGAffineTransformMakeTranslation([UIScreen mainScreen].bounds.size.width, 0);
}completion:^(BOOL finished) {
//无论转场是否被取消,动画是否执行完成都必须调用 .否则,系统不做其他事件处理,界面卡死.
[transitionContext completeTransition:!transitionContext.transitionWasCancelled];
}];
}
补充:
// 通过这个方法 能够获得前后两个 ViewController 的frame,用来布局视图对象空间位置
- (CGRect)initialFrameForViewController:(UIViewController *)vc;
- (CGRect)finalFrameForViewController:(UIViewController *)vc;