UIPinchGestureRecognizer仅用于捏出 [英] UIPinchGestureRecognizer only for pinching out

查看:107
本文介绍了UIPinchGestureRecognizer仅用于捏出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个UIPinchGestureRecognizer,如果用户捏出手指(将手指移开),该UIPinchGestureRecognizer将会失败.我知道有一种非常简单的方法,只需在动作方法中使用识别器的标度即可,如果该标度大于1,则设置一个标志并忽略所有将来的调用.但是,这对我不起作用,我还有其他手势识别器要求该捏捏识别器出现故障,因此当用户向错误的方向捏捏时,我需要使其正确失败.

我试图将UIPinchGestureRecognizer子类化:

@implementation BHDetailPinchGestureRecogniser {
    CGFloat initialDistance;
}

#pragma mark - Object Lifecycle Methods

- (id)initWithTarget:(id)target action:(SEL)action {
    self = [super initWithTarget:target action:action];
    if (self) {
        initialDistance = NSNotFound;
    }
    return self;
}

#pragma mark - UIGestureRecogniser Methods

- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)recogniser {
    if ([recogniser isKindOfClass:[UIPinchGestureRecognizer class]]) {
        return [self.delegate gestureRecognizerShouldBegin:self];
    } else return false;
}

- (void)reset {
    [super reset];
    initialDistance = NSNotFound;
}

#pragma mark - Touch Handling Methods

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touches.count >= 2) {
        if (self.state == UIGestureRecognizerStatePossible) {
            // Keep hold of the distance between the touches
            NSArray *bothTouches = [touches allObjects];
            CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view];
            CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view];
            initialDistance = [self distanceBetweenPoint:location1 andPoint:location2];
        }
    } else {
        // Fail if there is only one touch
        self.state = UIGestureRecognizerStateFailed;
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Moved. (tc, %lu) (state, %i) (id, %f)", (unsigned long)touches.count, self.state, initialDistance);
    if (touches.count >= 2) {
        if (self.state == UIGestureRecognizerStatePossible) {
            if (initialDistance != NSNotFound) {
                // Get the new distance and see if is is larger or smaller than the original
                NSArray *bothTouches = [touches allObjects];
                CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view];
                CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view];
                NSLog(@"Checking distance between points.");
                if ([self distanceBetweenPoint:location1 andPoint:location2] < initialDistance - 3.f) {
                    NSLog(@"Began");
                    self.state = UIGestureRecognizerStateBegan;
                } else if ([self distanceBetweenPoint:location1 andPoint:location2] > initialDistance) {
                    NSLog(@"Failed");
                    self.state = UIGestureRecognizerStateFailed;
                }
            }
        } else {
            self.state = UIGestureRecognizerStateChanged;
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.state == UIGestureRecognizerStatePossible) self.state = UIGestureRecognizerStateFailed;
    else [super touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    self.state = UIGestureRecognizerStateCancelled;
}

#pragma mark - Helper Methods

- (CGFloat)distanceBetweenPoint:(CGPoint)point1 andPoint:(CGPoint)point2 {
    return sqrtf(powf(point1.x - point2.x, 2) + powf(point1.y - point2.y, 2));
}

@end

我已经意识到这不是那么简单,它需要处理多个触摸,有时移动的触摸只有一个触摸,因此它需要保持触摸,一个触摸可能结束,而另一个开始,而这仍然想要成为捏的一部分.当我想要做的就是如果用户按错误的方向挤压时,使挤压识别器失效,这似乎使我失去了挤压识别器的内置功能.<​​/p>

是否存在一种无需完全重写UIPinchGestureRecognizer即可更简单地实现此行为的方法?可能值得一提的是,我无法控制要失败的其他识别器(它们位于PSPDFViewController(第三方库)的深处).

解决方案

如何使用手势识别器的delegate提供帮助?

使用gestureRecognizerShouldBegin

的以下实现设置委托

func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let pinch = gestureRecognizer as? UIPinchGestureRecognizer {
        return pinch.scale < 1
    }
    return true
}

I'm trying to create a UIPinchGestureRecognizer that fails if the user pinches out (moves there fingers apart). I know there is a really easy way to do this by just taking the scale of t he recogniser in the action method and if it is larger than 1, set a flag and ignore all the future calls. However, this does not work for me, I have other gesture recognisers that require this pinch recogniser to fail, so I need it to fail properly when the user pinches in the wrong direction.

I have attempted to subclass UIPinchGestureRecognizer:

@implementation BHDetailPinchGestureRecogniser {
    CGFloat initialDistance;
}

#pragma mark - Object Lifecycle Methods

- (id)initWithTarget:(id)target action:(SEL)action {
    self = [super initWithTarget:target action:action];
    if (self) {
        initialDistance = NSNotFound;
    }
    return self;
}

#pragma mark - UIGestureRecogniser Methods

- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)recogniser {
    if ([recogniser isKindOfClass:[UIPinchGestureRecognizer class]]) {
        return [self.delegate gestureRecognizerShouldBegin:self];
    } else return false;
}

- (void)reset {
    [super reset];
    initialDistance = NSNotFound;
}

#pragma mark - Touch Handling Methods

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touches.count >= 2) {
        if (self.state == UIGestureRecognizerStatePossible) {
            // Keep hold of the distance between the touches
            NSArray *bothTouches = [touches allObjects];
            CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view];
            CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view];
            initialDistance = [self distanceBetweenPoint:location1 andPoint:location2];
        }
    } else {
        // Fail if there is only one touch
        self.state = UIGestureRecognizerStateFailed;
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Moved. (tc, %lu) (state, %i) (id, %f)", (unsigned long)touches.count, self.state, initialDistance);
    if (touches.count >= 2) {
        if (self.state == UIGestureRecognizerStatePossible) {
            if (initialDistance != NSNotFound) {
                // Get the new distance and see if is is larger or smaller than the original
                NSArray *bothTouches = [touches allObjects];
                CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view];
                CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view];
                NSLog(@"Checking distance between points.");
                if ([self distanceBetweenPoint:location1 andPoint:location2] < initialDistance - 3.f) {
                    NSLog(@"Began");
                    self.state = UIGestureRecognizerStateBegan;
                } else if ([self distanceBetweenPoint:location1 andPoint:location2] > initialDistance) {
                    NSLog(@"Failed");
                    self.state = UIGestureRecognizerStateFailed;
                }
            }
        } else {
            self.state = UIGestureRecognizerStateChanged;
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.state == UIGestureRecognizerStatePossible) self.state = UIGestureRecognizerStateFailed;
    else [super touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    self.state = UIGestureRecognizerStateCancelled;
}

#pragma mark - Helper Methods

- (CGFloat)distanceBetweenPoint:(CGPoint)point1 andPoint:(CGPoint)point2 {
    return sqrtf(powf(point1.x - point2.x, 2) + powf(point1.y - point2.y, 2));
}

@end

What I have realised that it is not that simple, it will need to handle multiple touches, sometimes touches moved only has one touch so it will need to keep hold of the touches, one touch might end and another start and this still want to be part of the pinch. It seems like I am loosing the build in functionality of the pinch recogniser when all I want to do is make it fail if the user pinches in the wrong direction.

Is there a simpler way to achieve this behaviour without completely rewriting UIPinchGestureRecognizer? It is probably worth mentioning that I have no control over the other recognisers that I want to fail (they are deep in the bowls of a PSPDFViewController (third party library)).

解决方案

How about using the gesture recogniser's delegate to help?

Set a delegate with the following implementation of gestureRecognizerShouldBegin

func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let pinch = gestureRecognizer as? UIPinchGestureRecognizer {
        return pinch.scale < 1
    }
    return true
}

这篇关于UIPinchGestureRecognizer仅用于捏出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆