import UIKit
class ScreenPanGestureRecognizerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupInterface()
}
}
extension ScreenPanGestureRecognizerViewController {
private func setupInterface() {
setupGestureRecognizer()
}
private func setupGestureRecognizer() {
guard UIDevice.current.isPhone else { return }
// 以 iPhone SE 的 4 英寸为基准,大于这个尺寸宽度的才进行左侧边缘滑动返回手势的优化,扩大可触发的范围。
guard UIDevice.current.detailedModel.size.width > UIDevice.current.phone("SE").size.width else { return }
guard let target = navigationController?.interactivePopGestureRecognizer?.delegate else { return }
let sel = Selector(("handleNavigationTransition:"))
guard target.responds(to: sel) else { return }
let panGR = UIPanGestureRecognizer(target: target, action: sel)
panGR.delegate = self
view.addGestureRecognizer(panGR)
// 禁用系统自带的屏幕边缘滑动返回手势
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
// navigationController?.interactivePopGestureRecognizer?.delegate = self
}
}
extension ScreenPanGestureRecognizerViewController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// 当前视图控制器为 “根控制器” 时,则不触发滑动返回手势事件。
guard navigationController?.rootViewController != self else {
return false
}
let location = gestureRecognizer.location(in: view)
let width = view.bounds.width
// 以 iPhone SE 的 4 英寸为基准,大于这个尺寸宽度的才进行左侧边缘滑动返回手势的优化,扩大可触发的范围。
// 求出当前的差值,作为左侧滑动返回的可触发区域大小。
let factor = width - UIDevice.current.phone("SE").size.width
if location.x >= factor {
return false
}
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if children.count == 1 {
return false
}
// 手势不能同时进行触发,防止例如 UITableView 上下滑动手势与滑动返回手势冲突。
return false
}
}
fileprivate extension UINavigationController {
var rootViewController: UIViewController? {
return viewControllers.first
}
}
网友评论