项目里有需求要自定义返回按钮,在拦截全局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);
得到:
这个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;
}