CalZone
CalZone

Reputation: 1721

detect if user has tapped on an UIImageView

What I'm trying to achieve is to create a functionality that when user clicks on an image, it pushes to next VC in navController.

in ViewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)];
[singleTap setNumberOfTapsRequired:1];
[singleTap setNumberOfTouchesRequired:1];
[self.scroll addGestureRecognizer:singleTap];

in singleTapAction:

- (void)singleTapAction:(UIGestureRecognizer *)singleTap {
UIView *view = singleTap.view;
if([view isKindOfClass:[UIImageView class]]){
    NSLog(@"tapped on image");
}
else{
    NSLog(@"Just tapped");
}
}

The if-logic doesn't seem to be working. It always gives "Just tapped" in the log. Even when I click on UIImageView, it detects that I've clicked on scrollview, which is container of ImageView here.

(lldb) po view;
$0 = 0x1f5ed6e0 <UIScrollView: 0x1f5ed6e0; frame = (0 0; 320 416); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x1f5edc20>; layer = <CALayer: 0x1f5ecb80>; contentOffset: {0, 0}>

EDIT:

The way I am populating the scrollview with imageviews is:

ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
                             usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
                                 if (nil != group) {
                                     // be sure to filter the group so you only get photos
                                     [group setAssetsFilter:[ALAssetsFilter allPhotos]];
                                     NSLog(@"%d images found", group.numberOfAssets);
//                                         for(int i = group.numberOfAssets - 5; i<group.numberOfAssets - 1; i++){
                                     dispatch_apply(4, dispatch_get_global_queue(0, 0), ^(size_t i){
                                     [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:i]
                                                             options:0
                                                          usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
                                                              if (nil != result) {
                                                                  ALAssetRepresentation *repr = [result defaultRepresentation];
                                                                  // this is the most recent saved photo
                                                                  UIImage *img = [self fixrotation:[UIImage imageWithCGImage:[repr fullResolutionImage]]];
                                                                  UIImageOrientation orient = img.imageOrientation;
                                                                  NSLog(@"orientation: %d", orient);
                                                                  CGFloat aspectRatio = img.size.width/img.size.height;
                                                                  UIImageView *imgView = [[UIImageView alloc] init];

                                                                  imgView.frame = CGRectMake(10, self.yCord, 300, 300 /aspectRatio);

                                                                  self.yCord += margin + (300/aspectRatio);

                                                                  imgView.image = img;
                                                                  imgView.layer.shadowRadius = 5.0;
                                                                  imgView.layer.shadowColor = [UIColor blackColor].CGColor;

                                                                  imgView.layer.cornerRadius = 4.0;
                                                                  [imgView setUserInteractionEnabled:YES];
                                                                  [self.scroll addSubview:imgView];

                                                                  NSLog(@"%@", imgView);
                                                                  NSLog(@"%f, %f, %f, %f", imgView.frame.origin.x, imgView.frame.origin.y, imgView.frame.size.width, imgView.frame.size.height);
                                                                  *stop = YES;
                                                                  self.scrollViewHeight = self.yCord + imgView.frame.size.height + margin;
                                                                  CGSize scrollViewSize = CGSizeMake(320, self.scrollViewHeight);
                                                                  [self.scroll setContentSize:scrollViewSize];
                                                                  //self.scroll.frame = CGRectMake(0,0, 320, self.scrollViewHeight);
                                                              }
                                                          }];
                                                    });
                                 }
                                 *stop = NO;
                             } failureBlock:^(NSError *error) {
                                 NSLog(@"error: %@", error);
                             }];

Another question which comes up now is, does setUserInteraction works within block?

Upvotes: 1

Views: 1725

Answers (4)

Fogmeister
Fogmeister

Reputation: 77631

You can detect if the touch was inside the image view like this...

- (void)singleTapAction:(UIGestureRecognizer *)singleTap {
    CGPoint touchPoint = [singleTap locationInView:self.scroll];

    if(CGRectContainsPoint(self.tappableImageView.frame, touchPoint){
        NSLog(@"tapped on image");
    }
    else{
        NSLog(@"Just tapped");
    }
}

of if you have multiple image views then do something like this...

- (void)singleTapAction:(UIGestureRecognizer *)singleTap {
    CGPoint touchPoint = [singleTap locationInView:self.scroll];

    UIImageView *theTappedView;

    for (UIView *subView in [self.scroll subViews]) {
        if(CGRectContainsPoint(self.tappableImageView.frame, touchPoint)
               && [subView isKindOfClass:[UIImageView class]]) {
            theTappedView = subView;
            break;
        }
    }

    if(theTappedView != nil){
        NSLog(@"tapped on image");
    }
    else{
        NSLog(@"Just tapped");
    }
}

Note

This assumes that all the image views that will be tapped are subViews of the self.scroll scrollView.

Upvotes: 2

user4003752
user4003752

Reputation:

why don't you adding tap gesture on ImageView rather than

adding on scroll...

and make code

[self.imageView setUserInteractionEnabled:YES];

Upvotes: 4

Zhang
Zhang

Reputation: 11607

Why don't you use a UIButton instead?

You can set a custom image for your button.

That way, the button handles the tapping event for you rather than you writing your own tap gesture handler.

I notice in your code, you have:

UIView *view = gesture.view;

Have you tried to changing it to:

UIImageView *view = gesture.view;

By the way, when you add your image to your scrollview, you probably want to add your tap gesture recognizer to that image immediately rather than add it to your scrollview.

Upvotes: -1

Wain
Wain

Reputation: 119031

In your code singleTap.view is always the view that the tap gesture is attached to, not the view that you think was tapped.

You should create and attach a tap gesture for each image view individually rather than adding one to the container view.

Upvotes: 1

Related Questions