Visual_Novel_iOS/crush/Crush/Src/Components/Base/CLNavigationController.swift

152 lines
4.8 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// CLNavigationController.swift
// Crush
//
// Created by Leon on 2025/7/12.
//
import UIKit
protocol NavigationControllerDelegate: NSObjectProtocol {
func popGestureRecognizerShouldBegin() -> Bool
}
extension NavigationControllerDelegate {
func popGestureRecognizerShouldBegin() -> Bool {
return true
}
}
class CLNavigationController: UINavigationController {
weak var popDelegate: NavigationControllerDelegate?
private(set) var pan: UIPanGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.isHidden = true
modalPresentationStyle = .fullScreen
addFullScreenPan()
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
if viewControllers.count > 0 {
if viewController is CLBaseViewController {
let vc = viewController as! CLBaseViewController
vc.hiddenBackButton(of: false)
}
viewController.hidesBottomBarWhenPushed = true
}
// viewControllernavigationStackpush
if viewControllers.contains(viewController) {
return
}
super.pushViewController(viewController, animated: animated)
}
override open var childForStatusBarStyle: UIViewController? {
return topViewController
}
private func addFullScreenPan() {
// 1.Pop
guard let systemGes = interactivePopGestureRecognizer else { return }
// 2.View
guard let gesView = systemGes.view else { return }
// 3.target
let targets = systemGes.value(forKey: "_targets") as? [NSObject]
guard let targetObjc = targets?.first else { return }
guard let target = targetObjc.value(forKey: "target") else { return }
// 4.action
let action = Selector(("handleNavigationTransition:"))
// 5. pan
pan = UIPanGestureRecognizer()
gesView.addGestureRecognizer(pan)
pan.addTarget(target, action: action)
pan.delegate = self
}
///
func disabledFullScreenPan() {
pan.isEnabled = false
interactivePopGestureRecognizer?.delegate = self
}
///
func enabledFullScreenPan() {
pan.isEnabled = true
}
///
func disabledPopGesture() {
pan.isEnabled = false
interactivePopGestureRecognizer?.isEnabled = false
}
///
func enabledPopGesture() {
pan.isEnabled = true
interactivePopGestureRecognizer?.isEnabled = true
}
}
extension CLNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if viewControllers.count <= 1 {
return false
}
if value(forKey: "_isTransitioning") as? Bool ?? false {
return false
}
let translation = gestureRecognizer.location(in: gestureRecognizer.view)
if translation.x <= 0 {
return false
}
if let popDelegate = popDelegate {
return popDelegate.popGestureRecognizerShouldBegin()
}
return true
}
}
// MARK: -
extension UIScrollView: @retroactive UIGestureRecognizerDelegate {
// UIScrollView
override open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if panBack(gestureRecognizer: gestureRecognizer) {
return false
}
return true
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer) -> Bool {
if panBack(gestureRecognizer: gestureRecognizer) {
return true
}
return false
}
func panBack(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == panGestureRecognizer {
let point = panGestureRecognizer.translation(in: self)
let state = gestureRecognizer.state
//
let locationDistance = UIScreen.main.bounds.size.width
if state == UIGestureRecognizer.State.began || state == UIGestureRecognizer.State.possible {
let location = gestureRecognizer.location(in: self)
if point.x > 0, location.x < locationDistance, contentOffset.x <= 0 {
return true
}
}
}
return false
}
}