Here is the UIPanGesture subclass:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touches began");
self ->origLoc = [[touches anyObject] locationInView:self.view.superview];
[super touchesBegan:touches withEvent:event];
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (self.state == UIGestureRecognizerStatePossible) {
CGPoint loc = [[touches anyObject] locationInView:self.view.superview];
CGFloat deltaX = fabsf(loc.x - origLoc.x);
CGFloat deltaY = fabsf(loc.y - origLoc.y);
if (deltaY >= deltaX) {
self.state = UIGestureRecognizerStateFailed;
} else {
[super touchesMoved:touches withEvent:event];
}
}
}
- (CGPoint) translationInView:(UIView *)v {
CGPoint proposedTranslation = [super translationInView:v];
proposedTranslation.y = 0;
return proposedTranslation;
}
Here is the method that gets called by my subclassed UIPanGesture:
- (void)dragging: (UIPanGestureRecognizer *)p {
UIView *vv = p.view;
if (p.state == UIGestureRecognizerStateBegan || p.state == UIGestureRecognizerStateChanged) {
CGPoint delta = [p translationInView:vv.superview];
CGPoint c = vv.center;
c.x += delta.x;
c.y += delta.y;
vv.center = c;
[p setTranslation:CGPointZero inView:vv.superview];
}
}
When I try to drag my view around, it just moves a very small amount and then stops. I need to keep nudging it to get it to move. Any ideas?
Thanks in advance,
Michael.
In my prior comments, I wasn't clear why you were subclassing, but you clarified and it's because you have multiple gesture handlers going on. Very good.
So here is some sample code for a custom pan gesture, HorizontalPanGestureRecognizer, which is triggered only if the first movement is horizontal:
// HorizontalPanGestureRecognizer.h
#import <UIKit/UIKit.h>
@interface HorizontalPanGestureRecognizer : UIPanGestureRecognizer
@end
And
// HorizontalPanGestureRecognizer.m
#import "HorizontalPanGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
@interface HorizontalPanGestureRecognizer ()
{
BOOL _hasConfirmedDirection;
BOOL _wasHorizontal;
CGPoint _origLoc;
}
@end
@implementation HorizontalPanGestureRecognizer
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
_hasConfirmedDirection = NO;
_origLoc = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
if (!_hasConfirmedDirection)
{
CGPoint translation = [self translationInView:self.view];
_hasConfirmedDirection = YES;
_wasHorizontal = (fabs(translation.x) > fabs(translation.y));
}
if (!_wasHorizontal)
self.state = UIGestureRecognizerStateFailed;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
if (!_wasHorizontal)
self.state = UIGestureRecognizerStateFailed;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
if (!_wasHorizontal)
self.state = UIGestureRecognizerStateFailed;
}
- (CGPoint)locationInView:(UIView *)view
{
CGPoint superLocation = [super locationInView:view];
if (_hasConfirmedDirection)
superLocation.y = _origLoc.y;
return superLocation;
}
- (CGPoint)translationInView:(UIView *)view
{
CGPoint superTranslation = [super translationInView:view];
if (_hasConfirmedDirection)
superTranslation.y = 0.0f;
return superTranslation;
}
@end
And then you can have your handler in your main view controller use it appropriately (in this example, just dragging a UILabel around). In in viewDidLoad, create the gesture:
HorizontalPanGestureRecognizer *recognizer = [[HorizontalPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)];
[self.view addGestureRecognizer:recognizer];
And then the handler would look something like:
- (void)handleCustomPan:(UIPanGestureRecognizer *)sender
{
switch (sender.state) {
case UIGestureRecognizerStateChanged:
if (!_panLabel)
{
// In my case I'm creating a UILabel to drag around, whereas you might just drag
// whatever countrol you want to drag.
//
// But, regardless, I'm keeping track of the original center in _panLabelOrigCenter
[self makePanLabel:sender];
}
CGPoint translate = [sender translationInView:self.view];
_panLabel.center = CGPointMake(_panLabelOrigCenter.x + translate.x, _panLabelOrigCenter.y + translate.y);
break;
case UIGestureRecognizerStateEnded:
[self removePanLabel];
break;
default:
break;
}
}
(Obviously, this is ARC code. If non-ARC, add the necessary additional lines of code for routine memory management.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With