实现返回手势有两种比较简单的方式:
- 利用系统的边缘侧滑返回手势
- 给导航控制器加一个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)
网友评论