I'm trying to figure out the best way to handle pinch gestures in a UITextView. Currently I've been trying to handle it all in the UITextView, but I'm getting inconsistant results. It seems that it can catch my touches in the touches began method, but it doesn't always get caught in the touches moved method.
Would it be better to handle the touches in a View, and have the UITextView pass on the multitouch events? Would it be better to do something tricky like placing the UITextView in a scrollview?
At this point all I'd like to do is adjust the font size on a multitouch pinch or expand, which I can get to work, but it isn't consistant and I think I've managed to just confuse the UITextView more than actually get results.
My control is a subclass of UITextView and implements UITextViewDelegate:
#import "MyUITextView.h"
@implementation MyUITextView
/* skipping unimportant code */
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if([touches count] == 2)
{
NSLog(@"two touches");
UITouch *first = [[touches allObjects] objectAtIndex:0];
UITouch *second = [[touches allObjects] objectAtIndex:1];
initialDistance = [self distanceBetweenTwoPoints:[first locationInView:self] toPoint:[second locationInView:self]];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touches moved");
if([touches count] == 2)
{
self.scrollEnabled = NO;
UITouch *first = [[touches allObjects] objectAtIndex:0];
UITouch *second = [[touches allObjects] objectAtIndex:1];
CGFloat currentDistance = [self distanceBetweenTwoPoints:[first locationInView:self] toPoint:[second locationInView:self]];
if(initialDistance == 0)
initialDistance = currentDistance;
else if(currentDistance > initialDistance)
{
NSLog(@"zoom in");
self.scrollEnabled = YES;
self.font = [UIFont fontWithName:[self.font fontName] size:[self.font pointSize] + 1.0f];
self.text = self.text;
}
else if(currentDistance < initialDistance)
{
NSLog(@"zoom out");
self.scrollEnabled = YES;
self.font = [UIFont fontWithName:[self.font fontName] size:[self.font pointSize] = 1.0f];
self.text = self.text;
}
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touches ended.");
initialDistance = 0;
[super touchesEnded:touches withEvent:event];
}
-(CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint
{
float x = toPoint.x - fromPoint.x;
float y = toPoint.y - fromPoint.y;
return sqrt(x*x + y*y);
}
-(BOOL)canBecomeFirstResponder
{ return NO; }
Basically I've tried to disable the scrolling when I have two touches on the screen, and then re-enable it when I was done. Also, disabled the ability to become first responder so that I wouldn't have to be fighting with the copy and paste menu. If there is a better way to do this by allowing for the copy and paste menu when using a single touch I'm all ears. I think I'm basically working with a more advanced example for my first entry into this gesture business.
Also, since the control is handling all its own stuff, I didn't think it needed to pass on the touch events, since it is handling them itself. Am I wrong?
Finally, this UITextView of mine is created programatically and placed in a UINavigationControl. I don't know if that makes a difference or not.