自定义返回按钮,pop拦截push操作后,统一处理nav的返回手势

项目里有需求要自定义返回按钮,在拦截全局push方法之后,发现系统自带的返回手势不能用了。

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.childViewControllers.count > 0) {
      UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
      [btn setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal];
      [btn setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted];
      [btn setTitle:@"返回" forState:UIControlStateNormal];
      [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
      [btn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
      [btn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
      btn.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0);
      [btn sizeToFit];
      viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
    }
    [super pushViewController:viewController animated:animated];
}

思路:
考虑到返回手势和手势有关,进入UINavigationController头文件,搜索UIGestureRecognizer



找到属性:interactivePopGestureRecognizer
这时候猜测一下,手势失效的原因。1.为空值,2修改了代理方法。

self.interactivePopGestureRecognizer.delegate = nil;
将属性置空,确实解决问题,但是回到根目录左滑,会导致屏幕卡死,不能点击。

最后修改代理方法,代码如下:

//
//  LPNavigationController.m
//  BSBDJ
//
//  Created by 刘鹏 on 2019/10/12.
//  Copyright © 2019 刘鹏. All rights reserved.
//

#import "LPNavigationController.h"

@interface LPNavigationController ()

@end

@implementation LPNavigationController

+ (void)load {
    NSMutableDictionary *attDic = [NSMutableDictionary dictionary];
    attDic[NSFontAttributeName] = [UIFont systemFontOfSize:20];
    [[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[self class]]] setTitleTextAttributes:attDic];
    [[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[self class]]] setBackgroundImage:[UIImage imageNamed:@"navigationbarBackgroundWhite"] forBarMetrics:UIBarMetricsDefault];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.interactivePopGestureRecognizer.delegate = self;
}

- (void)back {
    [self popViewControllerAnimated:YES];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.childViewControllers.count > 0) {
        viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem itemwithImage:@"navigationButtonReturn" highImage:@"navigationButtonReturnClick" title:@"返回" target:self action:@selector(back)];
    }
    [super pushViewController:viewController animated:animated];
}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    return self.childViewControllers.count > 1;
}
@end

这时候只是保持了系统原有的滑动返回功能,只能从屏幕的最左侧向右边滑动。如果想在屏幕的其他地方,从左往右滑动,就需要继续来研究。

我们打印一下NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
得到:<_UINavigationInteractiveTransition: 0x7fe05b802650>

打印NSLog(@"%@", self.interactivePopGestureRecognizer);
得到:; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fd192510760>)>>

这个UIScreenEdgePanGestureRecognizer的父类是UIPanGestureRecognizer。

这个时候我们要重新给控制器的view添加一个滑动方法:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>];

上面打印的这行(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fd192510760>),就是系统内部调用的,我们可以直接拿来用。

- (void)viewDidLoad {
    [super viewDidLoad];
    
//    self.interactivePopGestureRecognizer.delegate = self;
    
//    NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
    //  <_UINavigationInteractiveTransition: 0x7f99f9d0cb10>
    
    //    NSLog(@"%@", self.interactivePopGestureRecognizer);
//    ; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7faab4c10280>)>>

    
    // 自己定义全屏滑动
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
    [self.view addGestureRecognizer:pan];
    // 用来配合代理方法,根控制器不能滑动,push的可以滑动
    pan.delegate = self;
    
    // 自己定义了返回手势,把系统的停用
    self.interactivePopGestureRecognizer.enabled = NO;
    
}

你可能感兴趣的:(自定义返回按钮,pop拦截push操作后,统一处理nav的返回手势)