Swiftgram/Display/NavigationController.swift
2015-07-30 01:09:30 +03:00

233 lines
12 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
public class NavigationController: NavigationControllerProxy, WindowContentController, UIGestureRecognizerDelegate {
private var _navigationBar: NavigationBar?
private var navigationTransitionCoordinator: NavigationTransitionCoordinator?
public override init() {
super.init()
self._navigationBar = NavigationBar()
self._navigationBar?.frame = CGRect(x: 0.0, y: 0.0, width: 320.0, height: 44.0)
self._navigationBar?.proxy = self.navigationBar as? NavigationBarProxy
self._navigationBar?.backPressed = { [weak self] in
if self?.viewControllers.count > 1 {
self?.popViewControllerAnimated(true)
}
return
}
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
public required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func loadView() {
super.loadView()
if let _navigationBar = self._navigationBar {
self.navigationBar.superview?.insertSubview(_navigationBar.view, aboveSubview: self.navigationBar)
}
self.navigationBar.removeFromSuperview()
self._navigationBar?.frame = navigationBarFrame(self.view.frame.size)
let panRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: Selector("panGesture:"))
panRecognizer.delegate = self
panRecognizer.cancelsTouchesInView = true
self.view.addGestureRecognizer(panRecognizer)
if self.topViewController != nil {
self.topViewController?.view.frame = CGRect(origin: CGPoint(), size: self.view.frame.size)
}
}
func panGesture(recognizer: UIPanGestureRecognizer) {
switch recognizer.state {
case UIGestureRecognizerState.Began:
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
topController.viewWillDisappear(true)
let topView = topController.view
bottomController.viewWillAppear(true)
let bottomView = bottomController.view
let navigationTransitionCoordinator = NavigationTransitionCoordinator(container: self.view, topView: topView, bottomView: bottomView, navigationBar: self._navigationBar!)
self.navigationTransitionCoordinator = navigationTransitionCoordinator
self._navigationBar?.beginInteractivePopProgress(bottomController.navigationItem, evenMorePreviousItem: self.viewControllers.count >= 3 ? (self.viewControllers[self.viewControllers.count - 3] as UIViewController).navigationItem : nil)
}
case UIGestureRecognizerState.Changed:
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
let translation = recognizer.translationInView(self.view).x
navigationTransitionCoordinator.progress = max(0.0, min(1.0, translation / self.view.frame.width))
}
case UIGestureRecognizerState.Ended:
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
let velocity = recognizer.velocityInView(self.view).x
if velocity > 1000 || navigationTransitionCoordinator.progress > 0.2 {
navigationTransitionCoordinator.animateCompletion(velocity, completion: {
self.navigationTransitionCoordinator = nil
self._navigationBar?.endInteractivePopProgress()
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
topController.setIgnoreAppearanceMethodInvocations(true)
bottomController.setIgnoreAppearanceMethodInvocations(true)
self.popViewControllerAnimated(false)
topController.setIgnoreAppearanceMethodInvocations(false)
bottomController.setIgnoreAppearanceMethodInvocations(false)
topController.viewDidDisappear(true)
bottomController.viewDidAppear(true)
}
})
}
else {
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
topController.viewWillAppear(true)
bottomController.viewWillDisappear(true)
}
navigationTransitionCoordinator.animateCancel({
self.navigationTransitionCoordinator = nil
self._navigationBar?.endInteractivePopProgress()
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
topController.viewDidAppear(true)
bottomController.viewDidDisappear(true)
}
})
}
}
case .Cancelled:
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
topController.viewWillAppear(true)
bottomController.viewWillDisappear(true)
}
navigationTransitionCoordinator.animateCancel({
self.navigationTransitionCoordinator = nil
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
topController.viewDidAppear(true)
bottomController.viewDidDisappear(true)
}
})
}
default:
break
}
}
public override func pushViewController(viewController: UIViewController, animated: Bool) {
var controllers = self.viewControllers
controllers.append(viewController)
self.setViewControllers(controllers, animated: animated)
}
public override func popViewControllerAnimated(animated: Bool) -> UIViewController? {
var controller: UIViewController?
var controllers = self.viewControllers
if controllers.count != 0 {
controller = controllers[controllers.count - 1] as UIViewController
controllers.removeAtIndex(controllers.count - 1)
self.setViewControllers(controllers, animated: animated)
}
return controller
}
public override func setViewControllers(viewControllers: [UIViewController], animated: Bool) {
if viewControllers.count > 0 {
let topViewController = viewControllers[viewControllers.count - 1] as UIViewController
if let controller = topViewController as? WindowContentController {
controller.setViewSize(self.view.bounds.size, duration: 0.0)
} else {
topViewController.view.frame = CGRect(origin: CGPoint(), size: self.view.bounds.size)
}
}
super.setViewControllers(viewControllers, animated: animated)
}
private func navigationBarFrame(size: CGSize) -> CGRect {
let condensedBar = (size.height < size.width || size.height <= 320.0) && size.height < 768.0
return CGRect(x: 0.0, y: 0.0, width: size.width, height: 20.0 + (size.height >= size.width ? 44.0 : 32.0))
}
public func setViewSize(toSize: CGSize, duration: NSTimeInterval) {
if duration > DBL_EPSILON {
animateRotation(self.view, toFrame: CGRect(x: 0.0, y: 0.0, width: toSize.width, height: toSize.height), duration: duration)
}
else {
self.view.frame = CGRect(x: 0.0, y: 0.0, width: toSize.width, height: toSize.height)
}
if duration > DBL_EPSILON {
animateRotation(self._navigationBar, toFrame: self.navigationBarFrame(toSize), duration: duration)
}
else {
self._navigationBar?.frame = self.navigationBarFrame(toSize)
}
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
//navigationTransitionView.frame = CGRectMake(0.0, 0.0, toSize.width, toSize.height)
if self.viewControllers.count >= 2 {
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
if let controller = bottomController as? WindowContentController {
controller.setViewSize(toSize, duration: duration)
}
bottomController.view.frame = CGRectMake(0.0, 0.0, toSize.width, toSize.height)
}
}
if let topViewController = self.topViewController {
if let controller = topViewController as? WindowContentController {
controller.setViewSize(toSize, duration: duration)
} else {
topViewController.view.frame = CGRectMake(0.0, 0.0, toSize.width, toSize.height)
}
}
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
navigationTransitionCoordinator.updateProgress()
}
}
public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}