iOS导航条设置自定义返回按钮系统右滑失效问题

2019-08-14  本文已影响0人  加盐白咖啡

仅供记录设置自定义返回按钮后,系统的手势滑动返回失效的解决办法


#import "JMCNavigationViewController.h"
#import <objc/runtime.h>

@interface JMCNavigationViewController () <UINavigationControllerDelegate, UIGestureRecognizerDelegate>
// 记录系统手势代理
@property (nonatomic, strong) id popGesture;
@end
@implementation JMCNavigationViewController

// 第一次初始化这个类调用,只调用一次
+ (void)initialize
{
    if (self == [JMCNavigationViewController class]) {
        // 获取导航条标识
        UINavigationBar *bar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[self]];
        
        // 设置导航条的背景图片,只能使用默认模式
        [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:(UIBarMetricsDefault)];
        // 设置导航字体颜色大小
        NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
        // 字体大小
        dictM[NSFontAttributeName] = [UIFont boldSystemFontOfSize:22];
        // 字体颜色
        dictM[NSForegroundColorAttributeName] = [UIColor whiteColor];
        
        [bar setTitleTextAttributes: dictM];
        
        //    // 另一种方式实现不带标题的返回按钮(不好使)
        //    // 设置颜色
        //    [bar setTintColor:[UIColor whiteColor]];
        //    // 获取当前导航栏的item
        //    UIBarButtonItem *item = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[self]];
        //    // 把返回标题移除到屏幕外面
        //    [item setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -100) forBarMetrics:UIBarMetricsDefault];
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // 恢复系统的滑动返回手势
    // 记录系统滑动手势代理
    self.popGesture = self.interactivePopGestureRecognizer.delegate;
    // 设置navigation代理
    self.delegate = self;

    // 全屏滑动移除控制器(系统默认是屏幕左侧滑动可以返回)
    UIScreenEdgePanGestureRecognizer *panS = self.interactivePopGestureRecognizer;
    
    // 打印私有属性
    // runtime 运行机制,只能获取当前类的私有属性
    //    unsigned int outCount = 0;
    //    Ivar *ivars = class_copyIvarList([UIGestureRecognizer class], &outCount);
    //    for (int i = 0 ; i < outCount; i++) {
    //        NSLog(@"%@",[NSString stringWithUTF8String:ivar_getName(ivars[i])]);
    //    }
    
    
    // 获取私有属性
    NSArray *targets = [panS valueForKey:@"_targets"];
    id target = [targets[0] valueForKey:@"target"];
    // 添加自己的手势到系统
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
    [self.view addGestureRecognizer:pan];
    // 添加代理,屏蔽根控制器禁止滑动,如果在根控制器滑动会卡死
    pan.delegate = self;
}

#pragma mark - UIGestureRecognizerDelegate 手势代理方法
// 开始滑动的时候会调用,返回YES 可以滑动,返回NO 不能滑动
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    // 如果大于1个控制器,就说明不是在根控制器,就返回YES
    return self.viewControllers.count > 1;
}

#pragma mark - UINavigationControllerDelegate 导航条代理方法
// 获取当前显示的控制器
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // 判断第一个是不是根控制器
    if (self.viewControllers[0] == viewController) {
        // 还原系统手势代理
        self.interactivePopGestureRecognizer.delegate = self.popGesture;
    } else
    {
        // 因为设置了返回键,清空系统手势代理,就能实现滑动
        self.interactivePopGestureRecognizer.delegate = nil;
    }
}

// 统一设置非根控制器的返回键
#pragma mark - 重写方法,统一设置返回键
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [super pushViewController:viewController animated:animated];
    // 设置非根控制器返回键
    // 如果在导航控制器设置统一返回按钮,就没有手势返回功能了
    if (self.viewControllers.count > 1) {
        // imageWithRenderOriginalName 分类中自定义的不渲染图片的方法
        viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageWithRenderOriginalName:@"NavBack"] style:0 target:self action:@selector(backClick)];
    }
}

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

@end

上一篇下一篇

猜你喜欢

热点阅读