美文网首页
手动实现滑动返回功能

手动实现滑动返回功能

作者: 冷洪林 | 来源:发表于2016-10-29 12:23 被阅读70次
    今天在项目的开发中自定义了导航条的返回按钮,导致覆盖了系统的滑动返回功能,侧滑无法返回上一个界面,解决方法如下:
    • 由于滑动返回是采用的收视识别,所以我们进入UINavigationController头文件搜索和手势有关的关键词,可以搜到@property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer,然后我们在viewDidLoad中打印这个手势,发现手势没有被清空
    • 既然手势没有被清空那么很可能就是这个手势的代理做了一些事情,导致手势失败,然后我们尝试清空代理:
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSLog(@"%@", self.interactivePopGestureRecognizer);
        self.interactivePopGestureRecognizer.delegate = nil;
    }
    
    • 清空代理后确实可以实现滑动返回了,但是会有BUG,就是我们在跟控制器的时候也进行滑动,接下来就会造成程序假死,所以我们不能这么暴力的清空代理
    • 我们应该把当前控制器设置为手势的代理,在代理方法中判断当前控制器是否是根控制器,如果是根控制器,则手势失效,如果非根控制器,则手势生效:
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSLog(@"%@", self.interactivePopGestureRecognizer);
        self.interactivePopGestureRecognizer.delegate = self;
    }
    
    • 代理方法:
    #pragma mark - UIGestureRecognizerDelegate
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
    {
        return self.childViewControllers.count > 1;
    }
    
    • 到此BUG解决,手动设置滑动返回也实现了,大功告成!

    !!!!!!!!!!!!!!!!!!但是,这还不能满足我们的需求,因为鄙人手指较短,喜欢滑动屏幕任何一个位置就返回上一个界面,嘿嘿,所以我们还要继续深入,实现全屏滑动返回:

    • 先打印NSLog(@"%@", self.interactivePopGestureRecognizer);看看里面有什么信息:
         <UIScreenEdgePanGestureRecognizer: 0x7f7f98c97430; 
         state = Possible; delaysTouchesBegan = YES; 
         view = <UILayoutContainerView 0x7f7f98f19d00>;
         target= <(action=handleNavigationTransition:,
         target=<_UINavigationInteractiveTransition 0x7f7f98c96ee0>)>
    
    • 可以发现self.interactivePopGestureRecognizer的类型是UIScreenEdgePanGestureRecognizer,我们可以跳进UIScreenEdgePanGestureRecognizer头文件看看,发现里面有@property (readwrite, nonatomic, assign) UIRectEdge edges;属性:
    • 从这里我们可以猜一下(因为iOS开发中好多都是要靠猜的,嘿嘿),会不会是边距导致的不能全屏滑动,接下来我们就设置一下这个属性:
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"%@", self.interactivePopGestureRecognizer);
    
        UIScreenEdgePanGestureRecognizer *edgePan = (UIScreenEdgePanGestureRecognizer *)self.interactivePopGestureRecognizer;
        edgePan.edges = UIRectEdgeNone;
        self.interactivePopGestureRecognizer.delegate = self;   
    }
    
    • 结果发现没有全屏滑动功能,而且连之前的边缘滑动效果也没有了,不顾不要气馁,总会有方法的,我们不妨换一种思路:有可能系统自带的手势根本就不支持全屏滑动返回,那么我们可不可以把系统的干掉,自己定义一个全屏滑动的手势呢?说干就干:

    • 但是问题又来了,我们的target和action该怎么设置呢,大家有没有留意到我们之前打印的NSLog(@"%@", self.interactivePopGestureRecognizer);呢?其实里面显示的就是系统自带滑动返回的target(其实这个target就是self.interactivePopGestureRecognizer.delegate)和action,我们可以巧妙的利用系统的方法(因为没门也不知道怎么做,嘿嘿),话不多少,上代码:

    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
    
        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
        [self.view addGestureRecognizer:pan];
        
    }
    
    • 现在已经实现全屏返回功能,但是还有两点:
      • 假死状态还会出现
      • 系统的边缘滑动手势已经没用了,应该禁止
    • 完善代码:
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
    
        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
        pan.delegate = self;
        self.interactivePopGestureRecognizer.enabled = NO;
        [self.view addGestureRecognizer:pan];
        
    }
    

    到此,滑动功能大功告成!

    相关文章

      网友评论

          本文标题:手动实现滑动返回功能

          本文链接:https://www.haomeiwen.com/subject/bcqyuttx.html