Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draggable UIView stops posting touchesBegan after being added to UIScrollView

In Xcode 5.1 I have created a simple test app for iPhone:

app screenshot

The structure is: scrollView -> contentView -> imageView -> image 1000 x 1000 on the top.

And on the bottom of the single view app I have seven draggable custom UIViews.

The dragging is implemented in Tile.m with touchesXXXX methods.

My problem is: once I add a draggable tile to the contentView in my ViewController.m file - I can not drag it anymore:

- (void) handleTileMoved:(NSNotification*)notification {
    Tile* tile = (Tile*)notification.object;
    //return;

    if (tile.superview != _scrollView && CGRectIntersectsRect(tile.frame, _scrollView.frame)) {
        [tile removeFromSuperview];
        [_contentView addSubview:tile];
        [_contentView bringSubviewToFront:tile];
    }
}

The touchesBegan isn't called for the Tile anymore as if the scrollView would mask that event.

I've searched around and there was a suggestion to extend the UIScrollView class with the following method (in my custom GameBoard.m):

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* result = [super hitTest:point withEvent:event];

    NSLog(@"%s: %hhd", __PRETTY_FUNCTION__,
          [result.superview isKindOfClass:[Tile class]]);

    self.scrollEnabled = ![result.superview isKindOfClass:[Tile class]];
    return result;
}

Unfortunately this doesn't help and prints 0 in debugger.

like image 762
Alexander Farber Avatar asked Mar 20 '23 05:03

Alexander Farber


1 Answers

The problem is, partly, because user interactions are disabled on the content view. However, enabling user interactions disables scrolling as the view captures all touches. So here is the solution. Enable user interactions in storyboard, but subclass the content view like so:

@interface LNContentView : UIView

@end

@implementation LNContentView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* result = [super hitTest:point withEvent:event];

    return result == self ? nil : result;
}

@end

This way, hit test passes only if the accepting view is not self, the content view.

Here is my commit: https://github.com/LeoNatan/ios-newbie

like image 140
Léo Natan Avatar answered Apr 02 '23 12:04

Léo Natan