I'm developing a card view like in Tinder. When cards X origin is bigger than a value which I declare, It moves out the screen. Otherwise, It sticks to center again. I'm doing all of these things inside UIPanGestureRecognizer
function. I can move the view in Change
state. However, It sometimes doesn't get into end state so card is neither moves out of the screen or stick to center again. It just stays in some weird place.
So My problem is that card should go out of the screen like in below screenshot or stick into center.
I tried solutions in below post but nothing worked:
UIPanGestureRecognizer not calling End state
/// This method handles the swiping gesture on each card and shows the appropriate emoji based on the card's center.
@objc func handleCardPan(sender: UIPanGestureRecognizer) {
// Ensure it's a horizontal drag
let velocity = sender.velocity(in: self.view)
if abs(velocity.y) > abs(velocity.x) {
return
}
// if we're in the process of hiding a card, don't let the user interace with the cards yet
if cardIsHiding { return }
// change this to your discretion - it represents how far the user must pan up or down to change the option
// distance user must pan right or left to trigger an option
let requiredOffsetFromCenter: CGFloat = 80
let panLocationInView = sender.location(in: view)
let panLocationInCard = sender.location(in: cards[0])
switch sender.state {
case .began:
dynamicAnimator.removeAllBehaviors()
let offset = UIOffsetMake(cards[0].bounds.midX, panLocationInCard.y)
// card is attached to center
cardAttachmentBehavior = UIAttachmentBehavior(item: cards[0], offsetFromCenter: offset, attachedToAnchor: panLocationInView)
//dynamicAnimator.addBehavior(cardAttachmentBehavior)
let translation = sender.translation(in: self.view)
print(sender.view!.center.x)
sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y)
sender.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
case .changed:
//cardAttachmentBehavior.anchorPoint = panLocationInView
let translation = sender.translation(in: self.view)
print(sender.view!.center.x)
sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x, y: sender.view!.center.y)
sender.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
case .ended:
dynamicAnimator.removeAllBehaviors()
if !(cards[0].center.x > (self.view.center.x + requiredOffsetFromCenter) || cards[0].center.x < (self.view.center.x - requiredOffsetFromCenter)) {
// snap to center
let snapBehavior = UISnapBehavior(item: cards[0], snapTo: CGPoint(x: self.view.frame.midX, y: self.view.frame.midY + 23))
dynamicAnimator.addBehavior(snapBehavior)
} else {
let velocity = sender.velocity(in: self.view)
let pushBehavior = UIPushBehavior(items: [cards[0]], mode: .instantaneous)
pushBehavior.pushDirection = CGVector(dx: velocity.x/10, dy: velocity.y/10)
pushBehavior.magnitude = 175
dynamicAnimator.addBehavior(pushBehavior)
// spin after throwing
var angular = CGFloat.pi / 2 // angular velocity of spin
let currentAngle: Double = atan2(Double(cards[0].transform.b), Double(cards[0].transform.a))
if currentAngle > 0 {
angular = angular * 1
} else {
angular = angular * -1
}
let itemBehavior = UIDynamicItemBehavior(items: [cards[0]])
itemBehavior.friction = 0.2
itemBehavior.allowsRotation = true
itemBehavior.addAngularVelocity(CGFloat(angular), for: cards[0])
dynamicAnimator.addBehavior(itemBehavior)
showNextCard()
hideFrontCard()
}
default:
break
}
}