How can I achieve Tinder effect in Swift?
I mean, I have an image and want to accept if I swipe to right and reject if I swipe to left.
I can do it with the
It's better to use UIPanGestureRecognizer here and manage its states, as you've already figured out. For managing cards it would be good solution to create class-manager that will handle interactions between cards(moving background cards on swiping the front). You can look at the implementation of card and manager here, there are implementation of dragging, moving background cards and revert animations. https://github.com/Yalantis/Koloda
Try this:
https://github.com/cwRichardKim/TinderSimpleSwipeCards
You can find a better solution here with rotation. See DraggableView.m
-(void)beingDragged:(UIPanGestureRecognizer *)gestureRecognizer
{
//%%% this extracts the coordinate data from your swipe movement. (i.e. How much did you move?)
xFromCenter = [gestureRecognizer translationInView:self].x; //%%% positive for right swipe, negative for left
yFromCenter = [gestureRecognizer translationInView:self].y; //%%% positive for up, negative for down
//%%% checks what state the gesture is in. (are you just starting, letting go, or in the middle of a swipe?)
switch (gestureRecognizer.state) {
//%%% just started swiping
case UIGestureRecognizerStateBegan:{
self.originalPoint = self.center;
break;
};
//%%% in the middle of a swipe
case UIGestureRecognizerStateChanged:{
//%%% dictates rotation (see ROTATION_MAX and ROTATION_STRENGTH for details)
CGFloat rotationStrength = MIN(xFromCenter / ROTATION_STRENGTH, ROTATION_MAX);
//%%% degree change in radians
CGFloat rotationAngel = (CGFloat) (ROTATION_ANGLE * rotationStrength);
//%%% amount the height changes when you move the card up to a certain point
CGFloat scale = MAX(1 - fabsf(rotationStrength) / SCALE_STRENGTH, SCALE_MAX);
//%%% move the object's center by center + gesture coordinate
self.center = CGPointMake(self.originalPoint.x + xFromCenter, self.originalPoint.y + yFromCenter);
//%%% rotate by certain amount
CGAffineTransform transform = CGAffineTransformMakeRotation(rotationAngel);
//%%% scale by certain amount
CGAffineTransform scaleTransform = CGAffineTransformScale(transform, scale, scale);
//%%% apply transformations
self.transform = scaleTransform;
[self updateOverlay:xFromCenter];
break;
};
//%%% let go of the card
case UIGestureRecognizerStateEnded: {
[self afterSwipeAction];
break;
};
case UIGestureRecognizerStatePossible:break;
case UIGestureRecognizerStateCancelled:break;
case UIGestureRecognizerStateFailed:break;
}
}
I would like to thanks the people who suggested solutions. Follow the solution I developed with a huge help of a lot of people from Stack Overflow:
@IBAction func Arrastei(sender: UIPanGestureRecognizer) {
var origem = CGPoint(x: 0, y: 0)
var translation : CGPoint = sender.translationInView(Imagem)
var txy : CGAffineTransform = CGAffineTransformMakeTranslation(translation.x, -abs(translation.x) / 15)
var rot : CGAffineTransform = CGAffineTransformMakeRotation(-translation.x / 1500)
var t : CGAffineTransform = CGAffineTransformConcat(rot, txy);
Imagem.transform = t
if (translation.x > 100) {
LbResultado.textColor = btVerdadeiro.textColor
LbResultado.text = btVerdadeiro.text
LbResultado.hidden = false
} else {
if (translation.x < -100) {
LbResultado.textColor = btFalso.textColor
LbResultado.text = btFalso.text
LbResultado.hidden = false
} else {
LbResultado.hidden = true
}
}
if sender.state == UIGestureRecognizerState.Ended {
if (translation.x > 100) {
objJogo.Rodada_Vigente!.Responder(true)
} else {
if (translation.x < -100) {
objJogo.Rodada_Vigente!.Responder(false)
} else {
sender.view.transform = CGAffineTransformMakeTranslation(origem.x, origem.y)
sender.view.transform = CGAffineTransformMakeRotation(0)
}
}
}
}
This solution uses:
Imagem --> UIImageView
- to be accepted or rejected
LbResultado --> UITextView
- to show the user he is in acceptance or rejection area
There is no math calculations to set rotation and translation. I used values that give me a visually good effect.
The action (acceptance and rejection) area is when the user drag image more than 100 pixels to left (reject) or right (accept). If the user ends the movement out the action area, the image will go back to its original position.
I will be glad if someone suggests improvements to this code.
Check this out Swift 4 library!!
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.beingDragged)) addGestureRecognizer(panGestureRecognizer)
func beingDragged(_ gestureRecognizer: UIPanGestureRecognizer) {
xFromCenter = gestureRecognizer.translation(in: self).x
yFromCenter = gestureRecognizer.translation(in: self).y
switch gestureRecognizer.state {
//%%% just started swiping
case .began:
originalPoint = self.center;
break;
//%%% in the middle of a swipe
case .changed:
let rotationStrength = min(xFromCenter / ROTATION_STRENGTH, ROTATION_MAX)
let rotationAngel = .pi/8 * rotationStrength
let scale = max(1 - fabs(rotationStrength) / SCALE_STRENGTH, SCALE_MAX)
center = CGPoint(x: originalPoint.x + xFromCenter, y: originalPoint.y + yFromCenter)
let transforms = CGAffineTransform(rotationAngle: rotationAngel)
let scaleTransform: CGAffineTransform = transforms.scaledBy(x: scale, y: scale)
self.transform = scaleTransform
updateOverlay(xFromCenter)
break;
case .ended:
afterSwipeAction()
break;
case .possible:break
case .cancelled:break
case .failed:break
}
}
Hope this will work . Let me know
https://github.com/nickypatson/TinderSwipeView
thanks