美文网首页
如何实现系统的全屏返回手势

如何实现系统的全屏返回手势

作者: galenu | 来源:发表于2018-04-27 15:27 被阅读0次

    实现返回手势有两种比较简单的方式:

      1. 利用系统的边缘侧滑返回手势
      1. 给导航控制器加一个UIPanGestureRecognizer,利用系统的返回Selector(("handleNavigationTransition:"))实现全屏左滑返回

    我们这里给UINavigationController实现了一个分类,代码如下:

    import UIKit
    
    // MARK: - 添加全屏返回手势
    extension UINavigationController: UIGestureRecognizerDelegate {
        
        /// 添加边缘返回
        func addEdgeScreenPopGesture(){
            self.interactivePopGestureRecognizer?.delegate = self
        }
        
        /// 添加全屏返回
        func addFullScreenPopGesture(){
            let panges = UIPanGestureRecognizer(target: self.interactivePopGestureRecognizer?.delegate, action: Selector(("handleNavigationTransition:")));
            panges.delegate = self;
            self.view.addGestureRecognizer(panges);
        }
        
        // MARK: - UIGestureRecognizerDelegate
    
        // 单个页面控制是否失效
        public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
            if (self.childViewControllers.count > 1 && (self.interactivePopGestureRecognizer?.isEnabled)!) {
                return true;
            } else {
                return false;
            }
        }
        
        /// 解决scrollView横向滑动手势覆盖屏幕边缘侧滑手势,返回无响应问题(需要在冲突的scrollView控制器中调用)
        ///
        /// - Parameter scrollView: 手势冲突的scrollView
        func handleEdgePopGestureConflict(scrollView: UIScrollView) {
            if let edgePan = self.getScreenEdgePanGestureRecognizer() {
                scrollView.panGestureRecognizer.require(toFail: edgePan)
            }
        }
        
        /// 越级pop(点击返回按钮或边缘返回时跨级,A push B push C,  C pop A, B push C时调用此方法,popStep为2)
        ///
        /// - Parameters:
        ///   - viewController: viewController
        ///   - popStep: 点击返回按钮或边缘返回时跨级步数
        func pushViewController(_ viewController: UIViewController, popStep: Int) {
            viewController.hidesBottomBarWhenPushed = true
            self.pushViewController(viewController, animated: true)
            let endIndex = self.viewControllers.count - 1
            let beginIndex = endIndex - popStep + 1
            self.viewControllers.removeSubrange(beginIndex ..< endIndex)
        }
        
        // MARK: - private
        
        /// 获取屏幕边缘侧滑手势
        fileprivate func getScreenEdgePanGestureRecognizer() -> UIScreenEdgePanGestureRecognizer? {
            var edgePan: UIScreenEdgePanGestureRecognizer?
            if let recognizers = view.gestureRecognizers, recognizers.count > 0 {
                for recognizer in recognizers {
                    if recognizer is UIScreenEdgePanGestureRecognizer {
                        edgePan = recognizer as? UIScreenEdgePanGestureRecognizer
                        break
                    }
                }
            }
            return edgePan
        }
        
        // MARK: - 特殊情况用法
        
        /// 当点击返回按钮(侧滑返回)需要做相关处理,则在这个特殊的控制器中添加此方法处理
    //    override func willMove(toParentViewController parent: UIViewController?) {
    //        if parent == nil {
    //            print("当点击返回按钮需要弹框确定后在返回,在这个特殊的控制器中添加此方法处理")
    //        }
    //    }
    }
    
    问题1: 当遇到横向滚动的scrollView时不响应侧滑返回
    • 需要在scrollView控制器中调用handleEdgePopGestureConflict
    • 或者通过函数
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {   
     }
    

    控制,给导航控制器关联一个是否模糊响应的变量(如isSimultaneouslyGesture),通过具体的控制器来设置是否模糊响应

    问题2:越级pop,点击返回按钮或边缘返回时跨级
    • 如A push B push C, C pop A, B push C时调用此方法,popStep为2(在B push C时移除导航控制器的中间部分的子控制器viewControllers)

    相关文章

      网友评论

          本文标题:如何实现系统的全屏返回手势

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