prerequisite: animationController(forDismissed:)
//MARK: - Interactive Transition
private var dismissInteractiveTransition = InteracitveTransition()
override func viewDidLoad() {
super.viewDidLoad()
addPanGestureRecognizer()
}
extension ChromecastExpandedViewController {
override func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return dismissInteractiveTransition.hasStarted ? dismissInteractiveTransition : nil
}
private func addPanGestureRecognizer() {
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
panGestureRecognizer.maximumNumberOfTouches = 1
view.addGestureRecognizer(panGestureRecognizer)
}
@objc private func didPan(sender: UIPanGestureRecognizer) {
let progressThreshold:CGFloat = 0.3
let progress = dismissProgress(of: sender)
switch sender.state {
case .began:
dismissInteractiveTransition.hasStarted = true
dismiss(animated: true, completion: nil)
case .changed:
dismissInteractiveTransition.shouldFinish = progress > progressThreshold
dismissInteractiveTransition.update(progress)
case .cancelled:
dismissInteractiveTransition.hasStarted = false
dismissInteractiveTransition.cancel()
case .ended:
dismissInteractiveTransition.hasStarted = false
dismissInteractiveTransition.shouldFinish
? dismissInteractiveTransition.finish()
: dismissInteractiveTransition.cancel()
default:
break
}
}
private func dismissProgress(of gestureRecognizer:UIPanGestureRecognizer) -> CGFloat {
let touchPoint = gestureRecognizer.translation(in: gestureRecognizer.view)
var downwardMovement = Float(touchPoint.y / view.bounds.height)
downwardMovement = fmaxf(downwardMovement, 0.0)
downwardMovement = fminf(downwardMovement, 1.0)
let progress = CGFloat(downwardMovement)
return progress
}
}
class InteracitveTransition: UIPercentDrivenInteractiveTransition {
var hasStarted = false
var shouldFinish = false
}