NavigationTransitionController
is a UINavigationController
that lets you implement interactive view controller transitions. It
manages the UIViewControllerInteractiveTransitioning
, UIViewControllerAnimatedTransitioning
, and UIViewControllerTransitioningDelegate
protocols for 4 unique transition types.
The current state of UIKit
requires a UIViewController
to conform to several protocols to implement a simple view controller transition. Not only that, but it also persists the standard UINavigationBar
transition when pushing or popping a view controller onto a navigation stack.
NavigationTransitionController
solves the complexity of this implementation by wrapping all of the setup in a UINavigationController
so that each UIViewController
can interface with interactive, animated transitions with its own persisting UINavigationBar
.
To simulate a view controller being "pushed" onto a standard navigation controller:
override func viewDidLoad() {
super.viewDidLoad()
// Initialize your view controller
let myVC = UIViewController()
// Pass it as a root view controller with the specified NavigationTransitionType
let navigationTransitionController = NavigationTransitionController(rootViewController: myVC, type: .standard)
navigationTransitionController.presentNavigation(self)
}
The NavigationTransitionController
comes out-of-the-box with 4 unique custom interactive animated transitions, accessible via the NavigationTransitionType
enums:
This simulates a view controller being "pushed" onto a standard navigation controller:
This simulates a view controller being "presented" from the bottom up. It restricts the root view controller's first scroll view subview without interfering its expected scrolling behavior (aka enable the transition to occur only when the UIScrollView
's contentOffset
reaches the top):
This simulates a view controller "fading-in" to the screen:
This simulates the iOS photos library transition. Unlike other dependencies, the setup and teardown is incredibly simple:
To configure the initial view transition:
// Define your image view for the initial view transition
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
override func viewDidLoad() {
super.viewDidLoad()
// Setup
view.addSubview(imageView)
imageView.center = view.center
// Initialize your view controller
let photoVC = UIViewController()
// MARK: - NavigationTransitionController
// Pass it as a root view controller with the specified NavigationTransitionType — here, we specify the initial view as the imageView
let navigationTransitionController = NavigationTransitionController(rootViewController: photoVC, type: .zoom, initialView: imageView)
navigationTransitionController.presentNavigation(self)
}
If the view ever changes, (i.e, you're displaying multiple photos in a horizontally scrolling UICollectionView
) update the NavigationTransitionController
's finalView
to persist the transitioning images to and from view controllers:
// Get the cell with the new image after we've scrolled and update the final view for the navigation transition controller's transition
if let cell = collectionView.cellForItem(at: indexPath) as? ImageCell {
self.navigationTransitionController?.updateFinalView(cell.imageView)
}
You can access the NavigationTransitionController
from within an arbitrary UIViewController
that's presented with it as you would with the standard UINavigationController
:
@objc func dismissViewController(_ sender: Any) {
// Dismiss the navigation transition view controller by accessing it (it's a UINavigationController subclass so you can also use ```.navigationController``` and cast it) — also call a completion if needed
self.navigationTransitionController?.dismissNavigation(animated: true, completion: { (dismissed: Bool) in
// Closure executed here
})
}
There are use-cases when one might need to observe a NavigationTransitionController
's gesture-driven transitions. For instance, when we want to disable the scroll view from scrolling with a NavigationTransitionType.presentation
transition:
// Enable or disable the scroll view based on the UIGestureRecognizer.State
self.navigationTransitionController?.interactiveTransitioningObserver = { (state: UIGestureRecognizer.State) in
let isScrollEnabled = (state == .began || state == .changed) ? false : true
self.scrollView.isScrollEnabled = isScrollEnabled
}
To disable the gesture entirely:
// Disable the gesture
self.navigationTransitionController?.panGestureRecognizer.isEnabled = false
- iOS 13+
To run the example project, clone the repo, and run pod install
from the Example directory first.
NavigationTransitionController is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'NavigationTransitionController'
NavigationTransitionController is available under the MIT license. See the LICENSE file for more info.