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

152 lines
4.8 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.

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