B.m 须遵守UIGestureRecognizerDelegate,并导入NavigationInteractiveTransition.h
全局变量
@property (nonatomic, strong) NavigationInteractiveTransition *navT;
viewDidLoad
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
UIGestureRecognizer *gesture = self.navigationController.interactivePopGestureRecognizer;
gesture.enabled = NO;
UIView *gestureView = gesture.view;
UIPanGestureRecognizer *popRecognizer = [[UIPanGestureRecognizer alloc] init];
popRecognizer.delegate = self;
popRecognizer.maximumNumberOfTouches = 1;
[gestureView addGestureRecognizer:popRecognizer];
_navT = [[NavigationInteractiveTransition alloc] initWithViewController:self.navigationController];
[popRecognizer addTarget:_navT action:@selector(handleControllerPop:)];
UIGestureRecognizerDelegate 代理方法gestureRecognizerShouldBegin
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
//记录当前是是否是通过手势滑动回去
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"isGesturePop"];
/**
* 这里有两个条件不允许手势执行,1、当前控制器为根控制器;2、如果这个push、pop动画正在执行(私有属性)
*/
return self.navigationController.viewControllers.count != 1 && ![[self.navigationController valueForKey:@"_isTransitioning"] boolValue];
}
需要依赖的两个类源码
NavigationInteractiveTransition.h
#import <UIKit/UIKit.h>
@class UIViewController, UIPercentDrivenInteractiveTransition;
@interface NavigationInteractiveTransition : NSObject <UINavigationControllerDelegate>
- (instancetype)initWithViewController:(UIViewController *)vc;
- (void)handleControllerPop:(UIPanGestureRecognizer *)recognizer;
- (UIPercentDrivenInteractiveTransition *)interactivePopTransition;
@end
NavigationInteractiveTransition.m
#import "NavigationInteractiveTransition.h"
#import "PopAnimation.h"
@interface NavigationInteractiveTransition ()
@property (nonatomic, weak) UINavigationController *vc;
@property (nonatomic, strong) UIPercentDrivenInteractiveTransition *interactivePopTransition;
@property(nonatomic, strong) UIImageView *barImageView;
@end
@implementation NavigationInteractiveTransition
- (instancetype)initWithViewController:(UIViewController *)vc
{
self = [super init];
if (self) {
self.vc = (UINavigationController *)vc;
self.vc.delegate = self;
}
return self;
}
/**
* 我们把用户的每次Pan手势操作作为一次pop动画的执行
*/
- (void)handleControllerPop:(UIPanGestureRecognizer *)recognizer {
/**
* interactivePopTransition就是我们说的方法2返回的对象,我们需要更新它的进度来控制Pop动画的流程,我们用手指在视图中的位置与视图宽度比例作为它的进度。
*/
CGFloat progress = [recognizer translationInView:recognizer.view].x / recognizer.view.bounds.size.width;
[self.vc.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.vc.navigationBar.shadowImage = [UIImage new];
self.barImageView = self.vc.navigationBar.subviews.firstObject;
CGFloat alpha = [[[NSUserDefaults standardUserDefaults] objectForKey:@"_alpha"] floatValue];
self.barImageView.alpha = 1 - progress > alpha ? alpha : 1 - progress;
// NSLog(@"===progress==%.2f",progress);
/**
* 稳定进度区间,让它在0.0(未完成)~1.0(已完成)之间
*/
progress = MIN(1.0, MAX(0.0, progress));
if (recognizer.state == UIGestureRecognizerStateBegan) {
/**
* 手势开始,新建一个监控对象
*/
self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
/**
* 告诉控制器开始执行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];
self.barImageView.alpha = 0;;
}
else {
[self.interactivePopTransition cancelInteractiveTransition];
}
self.interactivePopTransition = nil;
}
}
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC {
/**
* 方法1中判断如果当前执行的是Pop操作,就返回我们自定义的Pop动画对象。
*/
if (operation == UINavigationControllerOperationPop)
return [[PopAnimation alloc] init];
return nil;
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
/**
* 方法2会传给你当前的动画对象animationController,判断如果是我们自定义的Pop动画对象,那么就返回interactivePopTransition来监控动画完成度。
*/
if ([animationController isKindOfClass:[PopAnimation class]])
return self.interactivePopTransition;
return nil;
}
@end










