I'm trying to create a gesture recognizer able to detect the rotation of 4 fingers (similar when you rotate a volume knob).
The main idea was to create a subclass of UIRotateGestureRecognizer and override its method. In the -touchesBegan
I detect the number of touches, if the number is lower than 4 the state of the gesture is fail.
After that I pass the location point to an algorithm that find the diameter of a convex hull. If you think about it, your fingers are the vertices and I just need to find the two vertices with the max distance. Obtained these two points I reference them as ivar and I pass them to the superclass as it is a simple rotation with just two fingers.
It doesn't work:
- the detection of the touches seems pretty hard
- very rarely the
-touchesHasMoved
is called - when its called it hangs the most of time
Can someone help me?
Here is the code:
- (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];
}