Search code examples
ioshittestsubviewsuipinchgesturerecognizer

Add UIPinchGestureRecognizer on main view and detect touch on subviews


I added some subviews (UITextView) on main UIView ([self view]) to scale/pinch and dragging them around the screen. Everything works fine for ONE subview with a tag (mytextview1.tag = 1).

But how to tell the UIPinchGestureRecognizer that there is more than one subview? In other words: How to detect the current touched subview and give it a tag value? Some kind of hittest (one finger touch @ subview)?

I want to use the main view for usability reasons. I could attach this two finger gestue on every subview but they can be to small for scaling...

Here the code for ONE subview with a tag:

UIPinchGestureRecognizer *twoFingerPinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingerPinch:)];
[[self view] addGestureRecognizer:twoFingerPinch];


- (void)twoFingerPinch:(UIPinchGestureRecognizer *)recognizer
{
    NSLog(@"Pinch scale: %f", recognizer.scale);

    mytextview1.tag = 1; // please give an idea to detect current touched subview
    UITextView *myViewWithTag = (UITextView *)[self.view viewWithTag:1];

    UITextView *myViewWithTag = (UITextView *)recognizer.view;
    CGPoint location = [recognizer locationInView:recognizer.view];
    NSLog(@"location: %@", NSStringFromCGPoint(location));

    UIFont *font = [myViewWithTag font];
    CGFloat pointSize = [font pointSize];
    NSString *fontName = [font fontName];

    pointSize = ((recognizer.velocity > 0) ? 1.0 : -1.0) * 1 + pointSize;
    if (pointSize < 13) pointSize = 13;
    if (pointSize > 120) pointSize = 120;

    [myViewWithTag  setFont:[UIFont fontWithName:fontName size:pointSize]];

    CGRect frame = myViewWithTag.frame;
    frame.size.height = myViewWithTag.contentSize.height;
    myViewWithTag.frame = frame;
}

Solution

  • In twoFingerPinch: you may check the state of the gesture recognizer:

    If state is UIGestureRecognizerStateBegan then you detect via hitTest:withEvent: or custom routine the underlying view and store it somewhere (say ivar like UIView* _draggingView).

    If state is UIGestureRecognizerStateEnded or UIGestureRecognizerStateCancelled you forget that stored view (_draggingView = nil).

    If state is other then above you scale stored view (_draggingView).

    - (void)twoFingerPinch:(UIPinchGestureRecognizer *)recognizer
    {
        switch([recognizer state])
        {
            case UIGestureRecognizerStateBegan:
            {
                CGPoint location = [recognizer locationInView:recognizer.view];
                UIView* view = [recognizer.view hitTest:location withEvent:nil];
                if(%view is fine to use%)
                {
                    _draggingView = view;
                }
    
            break;
            }
    
    
            case UIGestureRecognizerStateEnded:
            case UIGestureRecognizerStateChanged:
            {
                _draggingView = nil;
    
            break;
            }
        }    
    
        if(_draggingView)
        {
            // scale _draggingView
        }
    }