Overview
Ever wonder how to create swipe cards like on the chrome app, tinder and many other apps? Well so did I. After reading many amazing tutorials, I decided to make a simplified version for myself. Here’s a list of the tutorials that inspired me.
- IOS - Creating a cool Tinder like drag animations By Nimrod Gutman
- How We Built Tinder-Like Koloda Animation in Swift By Eugene Andreyev
Content
There are 3 components that people seem to be using.
- DraggableCardView: card that displays content
- OverlayView: This is a dynamic view that is shown when people swipe to a side. (Think the Like, Dislike on tinder cards)
- DeckView: Loads the cards, shows them
Let’s start off simple.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ViewController: UIViewController {
var cardView:UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.cardView = createCardView()
self.view.addSubview(cardView)
}
override func viewWillLayoutSubviews() {
cardView.center = self.view.center
}
func createCardView() -> UIView {
let width = self.view.frame.width * 0.8
let height = self.view.frame.height * 0.8
let rect = CGRectMake(0, 0, width, height)
let tempCardView = UIView(frame: rect)
tempCardView.backgroundColor = UIColor.blueColor()
tempCardView.layer.cornerRadius = 8;
tempCardView.layer.shadowOffset = CGSizeMake(7, 7);
tempCardView.layer.shadowRadius = 5;
tempCardView.layer.shadowOpacity = 0.5;
return tempCardView
}
}
Step 1
We add a UIPanGestureRecognizer
on line 9 and 10. The method panGestureRecognized
on line 21 will handle what happens when the user tries to swipe.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class ViewController: UIViewController {
var cardView:UIView!
var panGestureRecognizer:UIPanGestureRecognizer!
var originalPoint: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "panGestureRecognized:")
self.view.addGestureRecognizer(panGestureRecognizer)
self.cardView = createCardView()
self.view.addSubview(cardView)
}
override func viewWillLayoutSubviews()
func createCardView() -> UIView
func panGestureRecognized(gestureRecognizer: UIPanGestureRecognizer) {
let xDistance = gestureRecognizer.translationInView(self.view).x
let yDistance = gestureRecognizer.translationInView(self.view).y
switch gestureRecognizer.state {
case .Began:
self.originalPoint = self.view.center
break
case .Changed:
updateCardViewWithDistances(xDistance, yDistance)
break
case .Ended:
resetViewPositionAndTransformations()
break
default:
break
}
}
}
We’re missing updateCardViewWithDistances
and resetViewPositionAndTransformations
.
Step 2
The function updateCardViewWithDistances
will update the rotation based on how far you drag the view.
It will also scale the view down for added effect.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func updateCardViewWithDistances(xDistance:CGFloat, _ yDistance:CGFloat) {
let rotationStrength = min(xDistance / 320, 1)
let fullCircle = (CGFloat)(2*M_PI)
let rotationAngle:CGFloat = fullCircle * rotationStrength / 16
let scaleStrength:CGFloat = (CGFloat) (1 - fabsf(Float(rotationStrength)) / 2)
let scale = max(scaleStrength, 0.93)
let newX = self.originalPoint.x + xDistance
let newY = self.originalPoint.y + yDistance
let transform = CGAffineTransformMakeRotation(rotationAngle)
let scaleTransform = CGAffineTransformScale(transform, scale, scale)
self.cardView.center = CGPointMake(newX, newY)
self.cardView.transform = scaleTransform
}
Step 3
The function resetViewPositionAndTransformations
will reset the center and transform back to normal.
1
2
3
4
5
6
func resetViewPositionAndTransformations() {
UIView.animateWithDuration(0.2, animations: {
self.cardView.center = self.originalPoint;
self.cardView.transform = CGAffineTransformMakeRotation(0);
})
}
Result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class ViewController: UIViewController {
var cardView:UIView!
var panGestureRecognizer:UIPanGestureRecognizer!
var originalPoint: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "panGestureRecognized:")
self.view.addGestureRecognizer(panGestureRecognizer)
self.cardView = createCardView()
self.view.addSubview(cardView)
}
override func viewWillLayoutSubviews() {
cardView.center = self.view.center
}
func createCardView() -> UIView {
let width = self.view.frame.width * 0.5
let height = self.view.frame.height * 0.5
let rect = CGRectMake(0, 0, width, height)
let tempCardView = UIView(frame: rect)
tempCardView.backgroundColor = UIColor.blueColor()
tempCardView.layer.cornerRadius = 8;
tempCardView.layer.shadowOffset = CGSizeMake(7, 7);
tempCardView.layer.shadowRadius = 5;
tempCardView.layer.shadowOpacity = 0.5;
return tempCardView
}
func panGestureRecognized(gestureRecognizer: UIPanGestureRecognizer) {
let xDistance = gestureRecognizer.translationInView(self.view).x
let yDistance = gestureRecognizer.translationInView(self.view).y
switch gestureRecognizer.state {
case .Began:
self.originalPoint = self.view.center
break
case .Changed:
updateCardViewWithDistances(xDistance, yDistance)
break
case .Ended:
resetViewPositionAndTransformations()
break
default:
break
}
}
func updateCardViewWithDistances(xDistance:CGFloat, _ yDistance:CGFloat) {
let rotationStrength = min(xDistance / 320, 1)
let fullCircle = (CGFloat)(2*M_PI)
let rotationAngle:CGFloat = fullCircle * rotationStrength / 16
let scaleStrength:CGFloat = (CGFloat) (1 - fabsf(Float(rotationStrength)) / 2)
let scale = max(scaleStrength, 0.93)
let newX = self.originalPoint.x + xDistance
let newY = self.originalPoint.y + yDistance
let transform = CGAffineTransformMakeRotation(rotationAngle)
let scaleTransform = CGAffineTransformScale(transform, scale, scale)
self.cardView.center = CGPointMake(newX, newY)
self.cardView.transform = scaleTransform
}
func resetViewPositionAndTransformations() {
UIView.animateWithDuration(0.2, animations: {
self.cardView.center = self.originalPoint;
self.cardView.transform = CGAffineTransformMakeRotation(0);
})
}
}