I have an IBAction
for a UIPanGestureRecognizer
in my UIView
, I am able to handle the gesture and recognise the state changes from began, cancelled and ended, as well as respond to those changes.
However when using the sender.location
to handle the swipe down, the UIView
actually moves up once the gesture has began, and then continues to move down. The experience is jarring and I am not sure what I am doing wrong. Does anybody have any ideas ?
func update(_ translation: CGPoint, origin: CGPoint) {
let offSetY = translation.y
cardView.frame.origin.y = offSetY
let multiplier = 1 - (translation.y / 2000)
self.view.alpha = multiplier
}
func cancel(_ origin: CGPoint) {
let animator = UIViewPropertyAnimator(duration: 0.6, dampingRatio: 0.6) {
self.visualEffectView.alpha = 1
self.cardView.alpha = 1.0
self.view.alpha = 1.0
self.cardView.center = origin
}
animator.startAnimation()
}
func finish() {
let animator = UIViewPropertyAnimator(duration: 0.9, dampingRatio: 0.9) {
self.visualEffectView.effect = nil
self.dismiss(animated: true, completion: nil)
}
animator.startAnimation()
}
@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) {
self.view.backgroundColor = .white
let originalCardPosition = cardView.center
//let cardOriginY = cardView.frame.origin.y
let translation = sender.translation(in: self.cardView)
let origin = sender.location(in: self.cardView)
switch sender.state {
case .changed:
if translation.y > 0 { update(translation, origin: origin) }
case .ended:
let translation = sender.translation(in: self.cardView)
if translation.y > 100 {
finish()
} else {
cardView.alpha = 1.0
cancel(originalCardPosition)
}
case .cancelled:
cancel(originalCardPosition)
default: break
}
}
The problem is that you set the origin.y
of the cardView
directly to the value of translation.y
. You need to add translation.y
to the view's original y
value determined when the gesture begins.
Add a property to the class:
var originalY: CGFloat = 0
Then in the .began
state of the gesture, set it:
originalY = cardView.frame.origin.y
Then in your update
method you set the origin:
cardView.frame.origin.y = originalY + offSetY