我正在尝试创建一个能够检测4个手指旋转的手势识别器(类似于旋转音量旋钮时)。
主要思想是创建UIRotateGestureRecognizer的子类并覆盖其方法。在-touchesBegan
我检测到触摸次数,如果该次数低于4,则手势状态失败。
之后我将位置点传递给找到凸包直径的算法。如果你考虑一下,你的手指就是顶点,我只需要找到最大距离的两个顶点。获得这两点我将它们称为ivar并将它传递给超类,因为它只用两根手指进行简单旋转。
它不起作用:
-touchesHasMoved
被称为有人可以帮助我吗?
以下是代码:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (touches.count<4) {
//FAIL
self.state = UIGestureRecognizerStateFailed;
return;
}
//Find the diameter of the convex hull
NSArray * touchesArray = [touches allObjects];
NSMutableArray * pointsArray = @[].mutableCopy;
for (UITouch * touch in touchesArray) {
[pointsArray addObject:[NSValue valueWithCGPoint:[touch locationInView:touch.view]]];
}
DiameterType convexHullDiameter = getDiameterFromPoints(pointsArray);
CGPoint firstPoint = convexHullDiameter.firstPoint;
CGPoint secondPoint = convexHullDiameter.secondPoint;
for (UITouch * touch in touchesArray) {
if (CGPointEqualToPoint([touch locationInView:touch.view], firstPoint) ) {
self.fistTouch = touch;
}
else if (CGPointEqualToPoint([touch locationInView:touch.view], secondPoint)){
self.secondTouch = touch;
}
}
//Calculating the rotation center as a mid point between the diameter vertices
CGPoint rotationCenter = (CGPoint) {
.x = (convexHullDiameter.firstPoint.x + convexHullDiameter.secondPoint.x)/2,
.y = (convexHullDiameter.firstPoint.y + convexHullDiameter.secondPoint.y)/2
};
self.rotationCenter = rotationCenter;
//Passing touches to super as a fake rotation gesture
NSSet * touchesSet = [[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil];
[super touchesBegan:touchesSet withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (touches.count<4) {
self.state = UIGestureRecognizerStateFailed;
return;
}
[super touchesMoved:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
}
- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
}
答案 0 :(得分:2)
初始检测困难的原因是所有触摸可能不会同时开始。 touchesBegan可能会被多次调用,因为屏幕上会出现单独的触摸。您可以使用event参数通过event.allTouches查询所有当前触摸。因此,您当前触发手势失败的方法将无效。如果touches.count是&lt ;,则不应将状态设置为失败。 4而是只返回if.allTouches.count&lt; 4.如果第四次触摸在第一次触摸后的某个时间内没有发生,您可以使用计时器将状态设置为失败。
touchesMoved可能存在问题,因为事件对象中的触摸与您传递给super的集合中的触摸不匹配。
答案 1 :(得分:1)
如果你考虑一下,你的手指就是顶点,我只需要找到最大距离的两个顶点。
即使你能够欺骗UIGestureRecognizer
,我也不认为这会在实践中发挥作用。
这就是我以“正确”的方式实现算法的方法:
对于两步前确定的4个手指中的每一个,计算角度以弧度为单位,近似为
new(i) - old(i) divided by distance to center
如果任何角度太大(> 0.5
),则失败。
恭喜,您现在拥有旋转角度(以弧度为单位)。
答案 2 :(得分:0)
如果我有足够的代表,我会把它放在评论中。
[super touchesMoved:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
您正在使用名为fistTouch
的内容,这听起来并不像您想要的那样。我的猜测是你想要firstTouch
。
此外,正在进行的手势之间可能存在可能相互重叠的冲突。您是否知道iOS7中有一个4指缩小图像是系统范围的手势?此外,应用程序中的4指放大将关闭它。