Skip to content

Instantly share code, notes, and snippets.

@DavidNix
Last active October 19, 2023 11:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidNix/d297696152315c1157b9ed553efa472f to your computer and use it in GitHub Desktop.
Save DavidNix/d297696152315c1157b9ed553efa472f to your computer and use it in GitHub Desktop.
iOS example of using UIViewControllerTransitioningDelegate to create a slide to reveal effect.
// A common effect when you press a hamburger button.
public class SlideRevealTransitioner: NSObject {
private let percentage: CGFloat
public init(percentage: CGFloat) {
self.percentage = percentage
}
private var presenting = true
}
extension SlideRevealTransitioner: UIViewControllerTransitioningDelegate {
public func animationControllerForPresentedController(presented: UIViewController,
presentingController presenting: UIViewController,
sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true
return self
}
public func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = false
return self
}
}
extension SlideRevealTransitioner: UIViewControllerAnimatedTransitioning {
public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.3
}
public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
guard let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey),
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
return
}
if presenting {
show(toVC, fromVC: fromVC, context: transitionContext)
} else {
hide(toVC, fromVC: fromVC, context: transitionContext)
}
}
}
private extension SlideRevealTransitioner {
func show(toVC: UIViewController, fromVC: UIViewController, context: UIViewControllerContextTransitioning) {
guard let containerView = context.containerView() else {
return
}
let finalFrame = CGRectOffset(fromVC.view.frame, fromVC.view.bounds.width * percentage, 0)
toVC.view.frame = fromVC.view.frame
containerView.addSubview(toVC.view)
let originalSuperview = fromVC.view.superview
containerView.addSubview(fromVC.view)
toVC.beginAppearanceTransition(true, animated: true)
UIView.animateWithDuration(transitionDuration(context), animations: {
fromVC.view.frame = finalFrame
}) { finished in
context.completeTransition(true)
originalSuperview?.addSubview(fromVC.view)
containerView.superview?.bringSubviewToFront(containerView)
toVC.endAppearanceTransition()
}
}
func hide(toVC: UIViewController, fromVC: UIViewController, context: UIViewControllerContextTransitioning) {
let containerView = context.containerView()
let finalFrame = context.finalFrameForViewController(toVC)
let originalSuperview = toVC.view.superview
containerView?.addSubview(toVC.view)
toVC.beginAppearanceTransition(true, animated: true)
UIView.animateWithDuration(transitionDuration(context), animations: {
toVC.view.frame = finalFrame
}) { finished in
originalSuperview?.addSubview(toVC.view)
fromVC.view.removeFromSuperview()
context.completeTransition(true)
toVC.endAppearanceTransition()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment