Skip to content

Instantly share code, notes, and snippets.

@skoirala
Created November 30, 2016 11:47
Show Gist options
  • Save skoirala/19b4cbec602548cee23bf6ae9e3ab414 to your computer and use it in GitHub Desktop.
Save skoirala/19b4cbec602548cee23bf6ae9e3ab414 to your computer and use it in GitHub Desktop.
Paging viewcontroller using interactive transitioning
import UIKit
extension UIColor {
static func randomColor() -> UIColor {
let red = CGFloat(arc4random_uniform(255)) / 255.0
let green = CGFloat(arc4random_uniform(255)) / 255.0
let blue = CGFloat(arc4random_uniform(255)) / 255.0
return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
}
class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
var interactionController: InteractionController?
var gestureRecognizer: UIPanGestureRecognizer?
var slidesRight = true
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.randomColor()
let panGestureRecognizer = UIPanGestureRecognizer(target: self,
action: #selector(panned))
view.addGestureRecognizer(panGestureRecognizer)
self.gestureRecognizer = panGestureRecognizer
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped))
view.addGestureRecognizer(tap)
}
@objc
func tapped(tapGestureRecognizer: UITapGestureRecognizer) {
let viewController = ViewController()
viewController.transitioningDelegate = self
present(viewController, animated: true, completion: nil)
}
@objc
func panned(panGestureRecognizer: UIPanGestureRecognizer) {
switch panGestureRecognizer.state {
case .began:
let translation = panGestureRecognizer.translation(in: view)
if fabs(translation.x) > 0 {
if translation.x == 0 {
return;
}
if translation.x < 0 {
slidesRight = true
let viewController = ViewController()
viewController.transitioningDelegate = self
present(viewController, animated: true, completion: nil)
} else {
slidesRight = false
let viewController = ViewController()
viewController.transitioningDelegate = self
present(viewController, animated: true, completion: nil)
}
}
default:
print("Not presenting")
}
}
public func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
self.interactionController = InteractionController(gestureRecognizer: gestureRecognizer!)
return self.interactionController!
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let slideDirection: SlideDirection = slidesRight ? .Right : .Left
return AnimationController(slideDirection: slideDirection)
}
}
class InteractionController: UIPercentDrivenInteractiveTransition {
let gestureRecognizer: UIPanGestureRecognizer
init(gestureRecognizer: UIPanGestureRecognizer) {
self.gestureRecognizer = gestureRecognizer
super.init()
self.gestureRecognizer.addTarget(self, action: #selector(panned))
}
override var completionSpeed: CGFloat {
get {
return 1.0 - self.percentComplete
}
set {}
}
@objc
func panned(pan: UIPanGestureRecognizer) {
switch pan.state {
case .changed:
let translation = gestureRecognizer.translation(in: gestureRecognizer.view!)
let ratio = (translation.x / gestureRecognizer.view!.bounds.size.width)
update(abs(ratio))
case .ended:
let translation = gestureRecognizer.translation(in: gestureRecognizer.view!)
let ratio = translation.x / gestureRecognizer.view!.bounds.size.width
if abs(ratio) > 0.30 {
finish()
} else {
cancel()
}
default:
print("Unrecognized state")
}
}
override func startInteractiveTransition(_ transitionContext: UIViewControllerContextTransitioning) {
super.startInteractiveTransition(transitionContext)
print("starting interactive transition")
}
}
enum SlideDirection {
case Left
case Right
}
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {
let slideDirection: SlideDirection
init(slideDirection: SlideDirection) {
self.slideDirection = slideDirection
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.33
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
let toView = transitionContext.view(forKey: .to)
let fromView = transitionContext.view(forKey: .from)
toView?.frame = containerView.bounds
fromView?.frame = containerView.bounds
var translationX: CGFloat = 0
if slideDirection == .Right {
translationX = containerView.bounds.size.width
} else {
translationX = -containerView.bounds.size.width
}
toView?.transform = CGAffineTransform(translationX: translationX, y: 0)
fromView?.transform = CGAffineTransform.identity
containerView.addSubview(toView!)
UIView.animate(withDuration: 0.33, delay: 0, options: .curveEaseInOut, animations: {
toView?.transform = CGAffineTransform.identity
fromView?.transform = CGAffineTransform(translationX: -translationX, y: 0)
}) { completed in
if transitionContext.transitionWasCancelled {
transitionContext.completeTransition(false)
fromView?.transform = CGAffineTransform.identity
} else {
transitionContext.completeTransition(true)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment