203 lines
7.2 KiB
Swift
203 lines
7.2 KiB
Swift
//
|
||
// JXNavigationInteractiveTransition.swift
|
||
// Test
|
||
//
|
||
// Created by 曾觉新 on 2022/10/10.
|
||
//
|
||
|
||
import UIKit
|
||
|
||
class JXNavigationInteractiveTransition: NSObject {
|
||
|
||
|
||
var interactionController: UIPercentDrivenInteractiveTransition?
|
||
|
||
var isGesturePush = false
|
||
|
||
weak var navigationController: UINavigationController!
|
||
weak var visibleVC: UIViewController?
|
||
|
||
}
|
||
|
||
extension JXNavigationInteractiveTransition {
|
||
|
||
@objc func panGestureRecognizerAction(_ sender: UIPanGestureRecognizer) {
|
||
guard let view = sender.view else { return }
|
||
|
||
|
||
var progress = sender.translation(in: view).x / UIScreen.main.bounds.width
|
||
let velocity = sender.velocity(in: sender.view)
|
||
|
||
|
||
// 在手势开始的时候判断是push操作还是pop操作
|
||
if sender.state == .began {
|
||
isGesturePush = velocity.x < 0 ? true : false
|
||
visibleVC = self.navigationController.visibleViewController
|
||
}
|
||
|
||
if isGesturePush {
|
||
progress = -progress
|
||
}
|
||
|
||
progress = min(1, max(0, progress))
|
||
// bcLog(message: progress)
|
||
|
||
switch sender.state {
|
||
case .began:
|
||
if self.isGesturePush {
|
||
if let visibleVC = self.visibleVC {
|
||
if visibleVC.jx_pushDelegate != nil {
|
||
self.interactionController = UIPercentDrivenInteractiveTransition()
|
||
visibleVC.jx_pushDelegate?.pushToNextViewController?()
|
||
self.pushScrollBegan()
|
||
}
|
||
}
|
||
} else {
|
||
self.interactionController = UIPercentDrivenInteractiveTransition()
|
||
self.navigationController.popViewController(animated: true)
|
||
self.popScrollBegan()
|
||
}
|
||
|
||
case .changed:
|
||
self.interactionController?.update(progress)
|
||
|
||
if self.isGesturePush {
|
||
self.pushScrollUpdate(progress: progress)
|
||
} else {
|
||
self.popScrollUpdate(progress: progress)
|
||
}
|
||
|
||
default:
|
||
|
||
var pushFinished: Bool = false
|
||
|
||
var finishProgress = 0.5
|
||
if self.isGesturePush {
|
||
finishProgress = 0.3
|
||
}
|
||
|
||
if progress > finishProgress {
|
||
pushFinished = true
|
||
self.interactionController?.finish()
|
||
} else {
|
||
pushFinished = false
|
||
self.interactionController?.cancel()
|
||
}
|
||
|
||
if self.isGesturePush {
|
||
pushScrollEnded(finished: pushFinished)
|
||
} else {
|
||
popScrollEnded(finished: pushFinished)
|
||
}
|
||
|
||
self.interactionController = nil
|
||
}
|
||
|
||
}
|
||
|
||
func pushScrollBegan() {
|
||
if let visibleVC = self.visibleVC {
|
||
visibleVC.jx_pushDelegate?.viewControllerPushScrollBegan?()
|
||
}
|
||
}
|
||
|
||
func pushScrollUpdate(progress: CGFloat) {
|
||
if let visibleVC = self.visibleVC {
|
||
visibleVC.jx_pushDelegate?.viewControllerPushScrollUpdate?(progress: progress)
|
||
}
|
||
}
|
||
|
||
func pushScrollEnded(finished: Bool) {
|
||
if let visibleVC = self.visibleVC {
|
||
visibleVC.jx_pushDelegate?.viewControllerPushScrollEnded?(finished: finished)
|
||
}
|
||
}
|
||
|
||
func popScrollBegan() {
|
||
if let visibleVC = self.visibleVC {
|
||
visibleVC.jx_popDelegate?.viewControllerPopScrollBegan?()
|
||
}
|
||
}
|
||
|
||
func popScrollUpdate(progress: CGFloat) {
|
||
if let visibleVC = self.visibleVC {
|
||
visibleVC.jx_popDelegate?.viewControllerPopScrollUpdate?(progress: progress)
|
||
}
|
||
}
|
||
|
||
func popScrollEnded(finished: Bool) {
|
||
if let visibleVC = self.visibleVC {
|
||
visibleVC.jx_popDelegate?.viewControllerPopScrollEnded?(finished: finished)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
extension JXNavigationInteractiveTransition: UIGestureRecognizerDelegate {
|
||
|
||
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||
// ydLog(message: "滑动========\(gestureRecognizer.jxTag ?? "")")
|
||
guard let jxTag = gestureRecognizer.jxTag else { return true }
|
||
|
||
// 忽略导航控制器正在做转场动画
|
||
if self.navigationController.jx_isTransitioning == true { return false }
|
||
|
||
// 如果没有visibleViewController,不作处理
|
||
guard let visibleVC = self.navigationController.visibleViewController else { return true }
|
||
|
||
//页面禁止了手势
|
||
if visibleVC.jx_popGestureType == .disabled { return false }
|
||
|
||
if let _ = gestureRecognizer as? UIScreenEdgePanGestureRecognizer {
|
||
if visibleVC.jx_popGestureType == .fullScreen { return false } //当前是全屏手势直接返回
|
||
// 修复边缘侧滑返回失效的bug
|
||
if self.navigationController.viewControllers.count <= 1 { return false }
|
||
// ydLog(message: "滑动========这里是边缘手势返回")
|
||
return true
|
||
|
||
} else if let panGesture = gestureRecognizer as? UIPanGestureRecognizer { //全屏滑动手势处理
|
||
// 根据transition判断是左滑还是右滑
|
||
let transition = panGesture.translation(in: gestureRecognizer.view)
|
||
if transition.x == 0 { return false }
|
||
|
||
if jxTag == "pop" {
|
||
if visibleVC.jx_popGestureType == .edge { return false }
|
||
if transition.x <= 0 { return false } //左滑直接返回
|
||
if self.navigationController.viewControllers.count <= 1 { return false }
|
||
if visibleVC.jx_popDelegate?.viewControllerPopShouldScrollBegan?() == false { return false }
|
||
visibleVC.jx_popDelegate?.viewControllerPopScrollBegan?()
|
||
// ydLog(message: "滑动========这里是pop滑动")
|
||
return true
|
||
} else if jxTag == "push" {
|
||
if transition.x >= 0 { return false } //右滑直接返回
|
||
if visibleVC.jx_pushDelegate == nil { return false }
|
||
// ydLog(message: "滑动========这里是push滑动")
|
||
return true
|
||
}
|
||
}
|
||
|
||
return true
|
||
}
|
||
}
|
||
|
||
extension JXNavigationInteractiveTransition: UINavigationControllerDelegate {
|
||
|
||
|
||
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||
if interactionController != nil, operation == .pop {
|
||
return JXPopAnimatedTransition()
|
||
} else if interactionController != nil, operation == .push {
|
||
return JXPushAnimatedTransition()
|
||
}
|
||
return nil
|
||
}
|
||
|
||
///处理交互式转场
|
||
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||
if animationController.isKind(of: JXBaseAnimatedTransition.self) {
|
||
return interactionController
|
||
}
|
||
return nil
|
||
}
|
||
}
|