         activeContext?.finishInteractiveTransition()
         
         UIView.animate(withDuration: duration,
-            delay: 0,
-            options: options,
-            animations: { () -> Void in
-                self.frontContainerView.transform = CGAffineTransform(
-                    translationX: maxDistance, y: 0
-                )
-                toView.transform = .identity
-                self.backOverlayView.alpha = 0.0
-                self.frontContainerView.dropShadowView.alpha = 0.0
+                       delay: 0,
+                       options: options,
+                       animations: { () -> Void in
+                        self.frontContainerView.transform = CGAffineTransform(
+                            translationX: maxDistance, y: 0
+                        )
+                        toView.transform = .identity
+                        self.backOverlayView.alpha = 0.0
+                        self.frontContainerView.dropShadowAlpha = 0.0
             },
-            completion: { (completed) -> Void in
-                fromView.removeFromSuperview()
-                self.frontContainerView.transform = .identity
-                self.frontContainerView.removeFromSuperview()
-                self.backOverlayView.removeFromSuperview()
-                self.activeContext?.completeTransition(true)
-                completion()
+                       completion: { (completed) -> Void in
+                        fromView.removeFromSuperview()
+                        self.frontContainerView.transform = .identity
+                        self.frontContainerView.removeFromSuperview()
+                        self.backOverlayView.removeFromSuperview()
+                        self.activeContext?.completeTransition(true)
+                        completion()
             }
         )
         
     }
-    
-    func percentDismissedForTranslation(_ translation: CGPoint, container: UIView) -> CGFloat {
+
+    // MARK: Private Methods
+    
+    private func prepForPop() {
+        
+        guard let transitionContext = activeContext,
+            let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from),
+            let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) else {
+                return
+        }
+        
+        let container = transitionContext.containerView
+        let containerBounds = container.bounds
+        
+        frontContainerView.frame = containerBounds
+        
+        let maxOffset = containerBounds.size.width * maxBackViewTranslationPercentage
+
+        fromView.frame = frontContainerView.bounds
+        frontContainerView.addSubview(fromView)
+        frontContainerView.transform = CGAffineTransform.identity
+        
+        toView.frame = containerBounds
+        toView.transform = CGAffineTransform(translationX: -maxOffset, y: 0)
+        
+        backOverlayView.frame = containerBounds
+        
+        container.addSubview(toView)
+        container.addSubview(backOverlayView)
+        container.addSubview(frontContainerView)
+    }
+    
+    private func updateViewsWithTranslation(_ translation: CGPoint) {
+        
+        guard let transitionContext = activeContext,
+            let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) else {
+                return
+        }
+        
+        let container = transitionContext.containerView
+        let maxDistance = container.bounds.size.width
+        let percent = percentDismissedForTranslation(translation, container: container)
+
+        let maxFromViewOffset = maxDistance
+
+        let maxToViewOffset = maxDistance * maxBackViewTranslationPercentage
+        let resolvedToViewOffset = -maxToViewOffset + (maxToViewOffset * percent)
+        
+        frontContainerView.transform = CGAffineTransform(translationX: maxFromViewOffset * percent, y: 0)
+        frontContainerView.dropShadowAlpha = (1.0 - percent)
+        toView.transform = CGAffineTransform(translationX: resolvedToViewOffset, y: 0)
+        backOverlayView.alpha = (1.0 - percent)
+        
+        activeContext?.updateInteractiveTransition(percent)
+    }
+    
+    private func percentDismissedForTranslation(_ translation: CGPoint, container: UIView) -> CGFloat {
         let maxDistance = container.bounds.size.width
         return (min(maxDistance, max(0, translation.x))) / maxDistance
     }
     
-    func durationForDistance(distance d: CGFloat, velocity v: CGFloat) -> TimeInterval {
+    private func durationForDistance(distance d: CGFloat, velocity v: CGFloat) -> TimeInterval {
         let minDuration: CGFloat = 0.08
         let maxDuration: CGFloat = 0.4
         return (TimeInterval)(max(min(maxDuration, d / v), minDuration))

    
}

private let defaultCancelPopDuration: TimeInterval = 0.16
private let maxBackViewTranslationPercentage: CGFloat = 0.30
private let minimumDismissalPercentage: CGFloat = 0.5
private let minimumThresholdVelocity: CGFloat = 100.0

private class InteractivePopAnimator: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerInteractiveTransitioning {
    
    var translation: CGPoint = CGPoint.zero {
        didSet {

@objc(JTSSloppySwiping)
class SloppySwiping: NSObject {
    
    // MARK: Init
    
    init(navigationController: UINavigationController) {
        self.interactivePopAnimator = InteractivePopAnimator()
        self.popRecognizer = UIPanGestureRecognizer()
