Uipangesturerecognizer - Only Vertical or Horizontal

UIPanGestureRecognizer - Only vertical or horizontal

I figured it out creating a subclass of UIPanGestureRecognizer

DirectionPanGestureRecognizer:

#import <Foundation/Foundation.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

typedef enum {
DirectionPangestureRecognizerVertical,
DirectionPanGestureRecognizerHorizontal
} DirectionPangestureRecognizerDirection;

@interface DirectionPanGestureRecognizer : UIPanGestureRecognizer {
BOOL _drag;
int _moveX;
int _moveY;
DirectionPangestureRecognizerDirection _direction;
}

@property (nonatomic, assign) DirectionPangestureRecognizerDirection direction;

@end

DirectionPanGestureRecognizer.m:

#import "DirectionPanGestureRecognizer.h"

int const static kDirectionPanThreshold = 5;

@implementation DirectionPanGestureRecognizer

@synthesize direction = _direction;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
CGPoint nowPoint = [[touches anyObject] locationInView:self.view];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view];
_moveX += prevPoint.x - nowPoint.x;
_moveY += prevPoint.y - nowPoint.y;
if (!_drag) {
if (abs(_moveX) > kDirectionPanThreshold) {
if (_direction == DirectionPangestureRecognizerVertical) {
self.state = UIGestureRecognizerStateFailed;
}else {
_drag = YES;
}
}else if (abs(_moveY) > kDirectionPanThreshold) {
if (_direction == DirectionPanGestureRecognizerHorizontal) {
self.state = UIGestureRecognizerStateFailed;
}else {
_drag = YES;
}
}
}
}

- (void)reset {
[super reset];
_drag = NO;
_moveX = 0;
_moveY = 0;
}

@end

This will only trigger the gesture if the user starts dragging in the selected behavior. Set the direction property to a correct value and you are all set.

Limit UIView movement to only vertical or horizontal axis

In gestureRecognizerShouldBegin: you can know that direction:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer {
CGPoint translation = [gestureRecognizer translationInView:self.view];
self.isVerticalPan = fabs(translation.y) > fabs(translation.x); // BOOL property

return YES;
}

And then on the UIGestureRecognizerStateChanged you could do something like this, based on isVerticalPan property:

CGPoint translation = [gesture translationInView:self.view];
CGPoint displacement = (self.isVerticalPan) ? CGPointMake(0, translation.y) : CGPointMake(translation.x, 0);

self.viewToMove.transform = CGAffineTransformMakeTranslation(displacement.x, displacement.y);

UIPanGesture recognizer swiping only in one direction

your same code just one changes in your UIGestureRecognizer method replace with this code and your problem solve. only left to right side swap work on your tableview cell . any query regrading this just drop comment below.

override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
let translation = panGestureRecognizer.translation(in: superview!)
if translation.x >= 0 {
return true
}
return false
}
return false
}

Good Luck.

Keep coding.

Horizontal Pan Inside Vertical Scrollview

You could use one of the UIGestureRecognizerDelegate methods like gestureRecognizerShouldBegin: to specify which pan gesture is triggered in which situation.

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

// If the gesture is a pan, determine whether it starts out more
// horizontal than vertical than act accordingly
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {

UIPanGestureRecognizer *panGestureRecognizer = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint velocity = [panGestureRecognizer velocityInView:self.view];

if (gestureRecognizer == self.scrollView.panGestureRecognizer) {
// For the vertical scrollview, if it's more vertical than
// horizontal, return true; else false
return fabs(velocity.y) > fabs(velocity.x);
} else {
// For the horizontal pan view, if it's more horizontal than
// vertical, return true; else false
return fabs(velocity.y) < fabs(velocity.x);
}
}
else
return YES;
}

Stop UIPanGestureRecognizer from moving UIView vertically when inside a UIScrollView

Try disabling scrolling on state begun and re-enabling it on state ended.

[scrollView setScrollEnabled:NO];    // in case UIGestureRecognizerStateBegan
[scrollView setScrollEnabled:YES]; // in case UIGestureRecognizerStateEnded

Horizontal scrolling UIScrollView with vertical pan gesture

I think this will be difficult if you want to use a pan gesture because of the scroll view's use of those gestures. However, if you could use a swipe, it is easy to implement.

    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
swipe.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp;
[self.scrollView addGestureRecognizer:swipe];

I tested this, and it worked fine to call the handler, and you don't need to disable the scroll view's pan gesture recognizer (in my test, the scroll view was tall enough and the content short enough that there was no vertical scrolling -- I don't know if this is necessary or not).

Simultaneously recognising UIPanGestureRecognizer, UIRotationGestureRecognizer, and UIPinchGestureRecognizer

Give this a try -- seems to work well for simultaneous Pan / Rotate / Scale:

class PinchPanRotateViewController: UIViewController, UIGestureRecognizerDelegate {

let testView: UILabel = {
let v = UILabel()
v.text = "TEST"
v.textAlignment = .center
v.textColor = .yellow

v.layer.cornerRadius = 4.0
v.layer.borderWidth = 4.0
v.layer.borderColor = UIColor.red.cgColor
v.layer.masksToBounds = true

//Enable multiple touch and user interaction
v.isUserInteractionEnabled = true
v.isMultipleTouchEnabled = true

return v
}()

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .blue

view.addSubview(testView)
testView.frame = CGRect(x: 0, y: 0, width: 240, height: 180)
testView.center = view.center

//add pan gesture
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
gestureRecognizer.delegate = self
testView.addGestureRecognizer(gestureRecognizer)

//add pinch gesture
let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(handlePinch(_:)))
pinchGesture.delegate = self
testView.addGestureRecognizer(pinchGesture)

//add rotate gesture.
let rotate = UIRotationGestureRecognizer.init(target: self, action: #selector(handleRotate(_:)))
rotate.delegate = self
testView.addGestureRecognizer(rotate)
}

@objc func handlePan(_ pan: UIPanGestureRecognizer) {
if pan.state == .began || pan.state == .changed {
guard let v = pan.view else { return }
let translation = pan.translation(in: self.view)
v.center = CGPoint(x: v.center.x + translation.x, y: v.center.y + translation.y)
pan.setTranslation(CGPoint.zero, in: self.view)
}
}

@objc func handlePinch(_ pinch: UIPinchGestureRecognizer) {
guard let v = pinch.view else { return }
v.transform = v.transform.scaledBy(x: pinch.scale, y: pinch.scale)
pinch.scale = 1
}

@objc func handleRotate(_ rotate: UIRotationGestureRecognizer) {
guard let v = rotate.view else { return }
v.transform = v.transform.rotated(by: rotate.rotation)
rotate.rotation = 0
}

func gestureRecognizer(_: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
return true
}

}

Detect vertical panning in UITableView

UITableView is a subclass of UIScrollview so you can get hold of it's panGestureRecognizer and add your own action targets.



Related Topics



Leave a reply



Submit