MoviaBox/ShortPlay/Thirdparty/JXTransition/JXNavigationInteractiveTransition.swift
2025-04-09 18:24:58 +08:00

203 lines
7.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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)
// pushpop
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
}
}