metatext/View Controllers/ImageNavigationController.swift
2020-11-08 22:22:20 -08:00

120 lines
4.2 KiB
Swift

// Copyright © 2020 Metabolist. All rights reserved.
import AVFoundation
import UIKit
final class ImageNavigationController: UINavigationController {
let transitionController = ZoomTransitionController()
private let imagePageViewController: ImagePageViewController
init(imagePageViewController: ImagePageViewController) {
self.imagePageViewController = imagePageViewController
super.init(rootViewController: imagePageViewController)
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
hidesBarsOnTap = true
modalPresentationStyle = .fullScreen
let panGestureRecognizer = UIPanGestureRecognizer(
target: self,
action: #selector(didPanWith(gestureRecognizer:)))
panGestureRecognizer.delegate = self
view.addGestureRecognizer(panGestureRecognizer)
transitioningDelegate = transitionController
transitionController.toDelegate = self
}
}
extension ImageNavigationController {
var currentViewController: ImageViewController? {
imagePageViewController.viewControllers?.first as? ImageViewController
}
@objc func didPanWith(gestureRecognizer: UIPanGestureRecognizer) {
guard let currentViewController = currentViewController else { return }
switch gestureRecognizer.state {
case .began:
currentViewController.scrollView.isScrollEnabled = false
transitionController.isInteractive = true
presentingViewController?.dismiss(animated: true)
case .ended:
if transitionController.isInteractive {
currentViewController.scrollView.isScrollEnabled = true
transitionController.isInteractive = false
transitionController.didPanWith(gestureRecognizer: gestureRecognizer)
}
default:
if transitionController.isInteractive {
transitionController.didPanWith(gestureRecognizer: gestureRecognizer)
}
}
}
}
extension ImageNavigationController: ZoomAnimatorDelegate {
func transitionWillStartWith(zoomAnimator: ZoomAnimator) {
}
func transitionDidEndWith(zoomAnimator: ZoomAnimator) {
}
func referenceView(for zoomAnimator: ZoomAnimator) -> UIView? {
if currentViewController?.playerView.player != nil {
return currentViewController?.playerView
} else {
return currentViewController?.imageView
}
}
func referenceViewFrameInTransitioningView(for zoomAnimator: ZoomAnimator) -> CGRect? {
guard let currentViewController = currentViewController else { return .zero }
let rect: CGRect
if let image = currentViewController.imageView.image {
rect = AVMakeRect(aspectRatio: image.size, insideRect: currentViewController.imageView.frame)
} else if let item = currentViewController.playerView.player?.currentItem {
rect = AVMakeRect(aspectRatio: item.presentationSize, insideRect: currentViewController.playerView.frame)
} else {
return .zero
}
return currentViewController.scrollView.convert(rect, to: currentViewController.view)
}
}
extension ImageNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if
let currentViewController = currentViewController,
otherGestureRecognizer == currentViewController.scrollView.panGestureRecognizer,
currentViewController.scrollView.contentOffset.y == 0 {
return true
}
return false
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
gestureRecognizer === barHideOnTapGestureRecognizer
&& (otherGestureRecognizer as? UITapGestureRecognizer)?.numberOfTapsRequired == 2
}
}