Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/110.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iOS中使用三个手指取消锁定自定义手势识别器_Ios_Iphone_Objective C_Ios7_Uipinchgesturerecognizer - Fatal编程技术网

在iOS中使用三个手指取消锁定自定义手势识别器

在iOS中使用三个手指取消锁定自定义手势识别器,ios,iphone,objective-c,ios7,uipinchgesturerecognizer,Ios,Iphone,Objective C,Ios7,Uipinchgesturerecognizer,我想用三个手指制作一个自定义手势识别器。这类似于手势识别器 我所需要的只是一个如何识别它的想法。 我的手势需要识别三个方向的三个手指。例如: 我希望图像有意义我需要使它在任何三个相反方向上都灵活。提前谢谢。任何帮助都将不胜感激 我知道子类方法,我已经用单手指创建了自定义手势,如半圆、全圆。我需要一个关于如何处理的编码想法。您需要创建自己的UIGestureRecognitor子类(我们称之为DRThreeFingerPinchGestureRecognitor),并在其中实现: – tou

我想用三个手指制作一个自定义手势识别器。这类似于手势识别器

我所需要的只是一个如何识别它的想法。

我的手势需要识别三个方向的三个手指。例如:

我希望图像有意义我需要使它在任何三个相反方向上都灵活。提前谢谢。任何帮助都将不胜感激


我知道子类方法,我已经用单手指创建了自定义手势,如半圆、全圆。我需要一个关于如何处理的编码想法。

您需要创建自己的
UIGestureRecognitor
子类(我们称之为
DRThreeFingerPinchGestureRecognitor
),并在其中实现:

– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:
这些方法在系统接受触摸时调用,可能在触摸发送到视图本身之前调用(取决于手势识别器的设置方式)。这些方法中的每一种都将为您提供一组触摸,您可以检查视图中的当前位置和以前的位置。由于按压手势相对来说非常简单,因此此信息足以让您测试用户是否正在进行按压,并使测试失败(
uigesturecognizerstatefiled
)。如果状态未通过
–touchesend:withEvent:
,则可以识别该手势

我说捏手势很简单,因为你可以很容易地跟踪每一次触摸,并观察它相对于其他触摸和自身的移动情况。如果某个角度的阈值通过并被打破,则测试失败,否则允许继续测试。如果触摸没有以单独的角度彼此移动,则测试失败。你必须考虑向量的角度是可以接受的,因为120度对于三个最常见的手指(拇指+食指+中指)不是最佳的。您可能只想检查向量是否没有碰撞


请务必阅读,以深入了解各种方法以及子类注释。

我认为轨迹角度将您引入错误的路径。我认为如果你不根据手指之间的角度来限制它,那么这可能是一个更灵活、更直观的手势。如果你只是把它当作三个手指的捏法来处理,不管手指之间是如何相对移动的,那么它就不那么容易出错。这就是我要做的:

if(presses != 3) {
     state = UIGestureRecognizerStateCancelled;
     return;
}

// After three fingers are detected, begin tracking the gesture.
state =  UIGestureRecognizerStateBegan; 
central_point_x = (point1.x + point2.x + point3.x) / 3;
central_point_y = (point1.y + point2.y + point3.y) / 3;

// Record the central point and the average finger distance from it.
central_point = make_point(central_point_x, central_point_y);
initial_pinch_amount = (distance_between(point1, central_point) + distance_between(point2, central_point) + distance_between(point3, central_point)) / 3;
然后,每次更新移动的触摸时:

if(presses != 3) {
     state = UIGestureRecognizerStateEnded;
     return;
}

// Get the new central point
central_point_x = (point1.x + point2.x + point3.x) / 3;
central_point_y = (point1.y + point2.y + point3.y) / 3;
central_point = make_point(central_point_x, central_point_y);

// Find the new average distance
pinch_amount = (distance_between(point1, central_point) + distance_between(point2, central_point) + distance_between(point3, central_point)) / 3;

// Determine the multiplicative factor between them.
difference_factor = pinch_amount / initial_pinch_amount
然后你可以用差分系数做任何你想做的事。如果大于1,则夹点已远离中心。如果它小于1,它就会向中心移动。这也将使用户能够保持两个手指静止,只移动第三个手指来执行手势。这将解决用户可能遇到的某些可访问性问题

此外,您可以始终跟踪触摸移动事件之间的增量变化,但它们的时间间隔不会相等,我怀疑您在处理这些事件时会遇到更多问题


我也为伪代码道歉。如果有什么不清楚的地方,我可以看一个真实的例子。

给未来读者的快速提示:用三个手指解开/捏的方法是加上ab、bc、ac的距离

但是,如果您的图形包正好有“三角形区域”
,只需使用它即可。(“它保存了一整行代码!”)

希望能有帮助


您只需跟踪:

三个手指之间的距离! 简单地将“每个”排列相加

(好的,有三个……ab,ac和cb。只要把它们加起来,就够了!)

比如说,当该值比起始值增加三倍时,即为“向外三英寸”

。。。令人惊讶的是,事情就这么简单

角度是无关紧要的


脚注如果你想成为一个聪明人:这适用于任何捏/拧手势,2、3个手指,无论什么:

跟踪总距离(我的意思是速度)的导数,而不是距离。(奇怪的是,这通常更容易做到!因为它是无状态的!您只需查看上一帧!!!!)

换句话说,当手指的伸展/收缩速度达到某个值,而不是起始值的倍数时,就会触发手势


更有趣的脚注

然而这里有一个微妙的问题:每当你做这样的事情(任何平台),你都必须小心地在玻璃上测量

如果你只是在做距离(即,我上面的第一个解决方案),当然所有的东西都会抵消,你可以说“如果它加倍”(以像素为单位——点——管它呢)。但是,如果你以任何姿势计算速度,那么有点奇怪,你必须在现实世界中以米/秒为单位找到速度,这听起来很奇怪!当然,你不能完全做到这一点(尤其是在android上),因为玻璃的大小有些不同,但你必须接近它。这里有一篇很长的文章讨论这个问题,在实践中,你通常不得不将就“每秒屏幕宽度”,这很好。(但这在手机、大型平板电脑和如今的“表面”型产品上可能有很大的不同。在整个iMac屏幕上,0.1屏幕宽度每秒可能很快,但在iPhone上,这并不是一种手势,什么都不是。)


最后的脚注!我只是不知道苹果是否在手势识别中使用了“距离倍数”或“玻璃速度”,或者可能是某种微妙的混合。我从来没有读过他们写的评论文章


另一个脚注如果出于任何原因,您确实想找到三角形的“中心”(我指的是三个手指的中心)。这是一个久经考验的问题
#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h>
@interface UnPinchGestureRecognizer : UIGestureRecognizer
 @property CGFloat averageDistanceFromCenter;
@end
#import "UnPinchGestureRecognizer.h"
@implementation UnPinchGestureRecognizer

-(CGPoint)centerOf:(CGPoint)pnt1 pnt2:(CGPoint)pnt2 pnt3:(CGPoint)pnt3
{
    CGPoint center;
    center.x = (pnt1.x + pnt2.x + pnt3.x) / 3;
    center.y = (pnt1.y + pnt2.y + pnt3.y) / 3;
    return center;
}
-(CGFloat)averageDistanceFromCenter:(CGPoint)center pnt1:(CGPoint)pnt1 pnt2:(CGPoint)pnt2 pnt3:(CGPoint)pnt3
{
    CGFloat distance;
    distance = (sqrt(fabs(pnt1.x-center.x)*fabs(pnt1.x-center.x)+fabs(pnt1.y-center.y)*fabs(pnt1.y-center.y))+
                sqrt(fabs(pnt2.x-center.x)*fabs(pnt2.x-center.x)+fabs(pnt2.y-center.y)*fabs(pnt2.y-center.y))+
                sqrt(fabs(pnt3.x-center.x)*fabs(pnt3.x-center.x)+fabs(pnt3.y-center.y)*fabs(pnt3.y-center.y)))/3;
    return distance;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    if ([touches count] == 3) {
        [super touchesBegan:touches withEvent:event];
        NSArray *touchObjects = [touches allObjects];
        CGPoint pnt1 = [[touchObjects objectAtIndex:0] locationInView:self.view];
        CGPoint pnt2 = [[touchObjects objectAtIndex:1] locationInView:self.view];
        CGPoint pnt3 = [[touchObjects objectAtIndex:2] locationInView:self.view];

        CGPoint center = [self centerOf:pnt1 pnt2:pnt2 pnt3:pnt3];
        self.averageDistanceFromCenter = [self averageDistanceFromCenter:center pnt1:pnt1 pnt2:pnt2 pnt3:pnt3];
        self.state = UIGestureRecognizerStateBegan;
    }
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    if ([touches count] == 3)
    {
        NSArray *touchObjects = [touches allObjects];
        CGPoint pnt1 = [[touchObjects objectAtIndex:0] locationInView:self.view];
        CGPoint pnt2 = [[touchObjects objectAtIndex:1] locationInView:self.view];
        CGPoint pnt3 = [[touchObjects objectAtIndex:2] locationInView:self.view];

        CGPoint center = [self centerOf:pnt1 pnt2:pnt2 pnt3:pnt3];
        self.averageDistanceFromCenter = [self averageDistanceFromCenter:center pnt1:pnt1 pnt2:pnt2 pnt3:pnt3];
        self.state = UIGestureRecognizerStateChanged;
        return;
    }

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

@end
-(IBAction)handleUnPinch:(UnPinchGestureRecognizer *)sender
{
    switch (sender.state) {
        case UIGestureRecognizerStateBegan:
            //If you want a maximum starting distance
            self.validPinch = (sender.averageDistanceFromCenter<75);
            break;
        case UIGestureRecognizerStateEnded:
            //Minimum distance from relative center
            if (self.validPinch && sender.averageDistanceFromCenter >=150) {
                NSLog(@"successful unpinch");
            }
            break;
        default:
            break;
    }
}