Reputation: 815
So Im making a page with pageControl (it's a page with multiple views with dots indicating which page you're in), my code looks like the following in viewDidLoad
:
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
UIView *temp = [[UIView alloc]initWithFrame:self.view.frame];
temp.backgroundColor = [UIColor clearColor];
[temp addGestureRecognizer:swipe];
[self.view addSubview:temp];
And in the swipeAction selector I have:
- (void)swipeAction: (UISwipeGestureRecognizer *)sender{
NSLog(@"Swipe action called");
if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {
//Do Something
}
else if (sender.direction == UISwipeGestureRecognizerDirectionRight){
//Do Something Else
}
}
To my surprise, this method only works when you swipe to the right (i.e. the else if
block gets called). When you swipe left, the swipeAction
doesn't even get called! This is strange, why does this happen and how should I change my code? Any reply is appreciated. Thanks a lot!
Upvotes: 6
Views: 6955
Reputation: 483
I was facing the same issue and found a way by extending the UIPanGestureRecognizer
in order to implement a UIDirectionalSwipeGestureRecognizer
as follows. The direction
of the swipe is available as a public property of the recognizer's instance:
import UIKit
public final class UIDirectionalSwipeGestureRecognizer: UIPanGestureRecognizer {
public private(set) var direction: UISwipeGestureRecognizer.Direction?
public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
direction = nil
if let touch = touches.first {
startTimestamp = touch.timestamp
startLocation = touch.location(in: nil)
}
}
public override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
if
let currentTimestamp = touches.first?.timestamp,
let startTimestamp = startTimestamp,
currentTimestamp - startTimestamp > 0.3
{
touchesCancelled(touches, with: event)
}
}
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event)
if
let endLocation = touches.first?.location(in: nil),
let startLocation = startLocation,
startLocation.distance(to: endLocation) > 20
{
direction = UISwipeGestureRecognizer.Direction.fromPoint(startLocation, to: endLocation)
}
}
// MARK: - Private
private var startTimestamp: TimeInterval?
private var startLocation: CGPoint?
}
// MARK: - Extensions
public extension CGPoint {
func distanceSquared(to: CGPoint) -> CGFloat {
(to.x - x) * (to.x - x) + (to.y - y) * (to.y - y)
}
func distance(to: CGPoint) -> CGFloat {
sqrt(distanceSquared(to: to))
}
}
extension UISwipeGestureRecognizer.Direction {
public static func fromPoint(_ startPoint: CGPoint, to endPoint: CGPoint) -> Self {
let offset = CGSize(width: endPoint.x - startPoint.x, height: endPoint.y - startPoint.y)
if abs(offset.width) > abs(offset.height) {
return offset.width > 0 ? .right : .left
} else {
return offset.height > 0 ? .up : .down
}
}
}
Upvotes: 0
Reputation: 35
Swift 4
let swiper = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeFunction(sender:)))
swiper.direction = UISwipeGestureRecognizer.Direction.right
let swipel = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeFunction(sender:)))
swipel.direction = UISwipeGestureRecognizer.Direction.left
UIView().addGestureRecognizer(swiper)
UIView().addGestureRecognizer(swipel)
@objc func swipeFunction(sender: UISwipeGestureRecognizer) {
print(sender)
}
you should be able to figure it out from there, you add a UISwipeGestureRecognizer for each direction to the UIView
Upvotes: 2
Reputation: 130193
There's a couple things you should be aware of here. First, you have to create a gesture for each direction that you want to observe. This isn't a big deal though because you can simple give them the same selector, and it will be just like one gesture for two directions.
UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
UIView *temp = [[UIView alloc]initWithFrame:self.view.frame];
temp.backgroundColor = [UIColor clearColor];
[temp addGestureRecognizer:leftSwipe];
[temp addGestureRecognizer:rightSwipe];
[self.view addSubview:temp];
Second, you never specified the direction of the gesture leaving it to default to right (or 1 on the direction enum)
From the documentation:
The default direction is UISwipeGestureRecognizerDirectionRight. See descriptions of UISwipeGestureRecognizerDirection constants for more information.
typedef enum {
UISwipeGestureRecognizerDirectionRight = 1 << 0,
UISwipeGestureRecognizerDirectionLeft = 1 << 1,
UISwipeGestureRecognizerDirectionUp = 1 << 2,
UISwipeGestureRecognizerDirectionDown = 1 << 3
} UISwipeGestureRecognizerDirection;
Upvotes: 13
Reputation: 32954
swipe.direction sets the direction(s) you're recognizing, it doesn't tell you which direction was swiped. Add this line when creating your recognizer:
swipe.direction = UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight;
If you need to detect which direction was swiped, just use two different Recognizers, one for left and one for right.
Upvotes: 1