Skip to content

Instantly share code, notes, and snippets.

@alfian0
Last active June 24, 2020 08:03
Show Gist options
  • Save alfian0/bee0c01432946b090a1c08f99ec22629 to your computer and use it in GitHub Desktop.
Save alfian0/bee0c01432946b090a1c08f99ec22629 to your computer and use it in GitHub Desktop.
Custom Transition
class CustomPresentation: UIPresentationController {
override var frameOfPresentedViewInContainerView: CGRect {
return CGRect(x: 0, y: containerView!.bounds.height / 2, width: containerView!.bounds.width, height: containerView!.bounds.height / 2)
}
override func containerViewWillLayoutSubviews() {
presentedView?.center = .zero
presentedView?.frame = frameOfPresentedViewInContainerView
}
}
extension CustomTransition: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return CustomPresentation(presentedViewController: presented, presenting: presenting)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
state = .present
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
state = .dismiss
return self
}
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
let interactor = Interactor()
return interactor.hasStarted ? interactor : nil
}
}
class CustomTransition: NSObject, UIViewControllerAnimatedTransitioning {
enum TransitionState {
case present
case dismiss
}
private var state: TransitionState = .present
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
let duration = transitionDuration(using: transitionContext)
switch state {
case .present:
present(duration: duration, container: container, transitionContext: transitionContext)
case .dismiss:
dismiss(duration: duration, container: container, transitionContext: transitionContext)
}
}
private func present(duration: TimeInterval, container: UIView, transitionContext: UIViewControllerContextTransitioning) {
let from = transitionContext.viewController(forKey: .from)!
let to = transitionContext.viewController(forKey: .to)!
let toFinalFrame = transitionContext.finalFrame(for: to)
container.addSubview(from.view)
container.insertSubview(to.view, aboveSubview: from.view)
to.view.frame = CGRect(x: 0, y: toFinalFrame.height, width: toFinalFrame.width, height: toFinalFrame.height)
UIView.animate(withDuration: duration, animations: {
to.view.frame = CGRect(x: 0, y: 0, width: toFinalFrame.width, height: toFinalFrame.height)
}) { (_) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
private func dismiss(duration: TimeInterval, container: UIView, transitionContext: UIViewControllerContextTransitioning) {
let from = transitionContext.viewController(forKey: .from)!
let fromFinalFrame = transitionContext.finalFrame(for: from)
UIView.animate(withDuration: duration, animations: {
from.view.frame = CGRect(x: 0, y: container.bounds.height, width: fromFinalFrame.width, height: fromFinalFrame.height)
}) { (_) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
class Interactor: UIPercentDrivenInteractiveTransition {
var hasStarted = false
var shouldFinish = false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment