How can I detect the touch event of an UIImageView?
Asked Answered
C

10

98

I have placed an image (UIImageView) on the navigation bar. Now I want to detect the touch event and want to handle the event. How can I do that?

Clairclairaudience answered 12/5, 2009 at 22:2 Comment(2)
In this situation I would (and think you should) use a custom UIButton instead.Lexielexigraphy
Check Swift version Answer https://mcmap.net/q/209448/-click-event-on-uiimageview-programmatically-in-iosPalaeobotany
G
138

In practical terms, don't do that.

Instead add a button with Custom style (no button graphics unless you specify images) over the UIImageView. Then attach whatever methods you want called to that.

You can use that technique for many cases where you really want some area of the screen to act as a button instead of messing with the Touch stuff.

Ganiats answered 13/5, 2009 at 6:44 Comment(5)
I have added a button at the navigation bar and I can also handle touch events. However, I want to add an round image on this button. Could you let me know how can I do that programmatically? Also, could you let me know how can I set the button property to "custom" programmatically?Clairclairaudience
Look at the docs for UIButton - you need to set background images for a control state, you'll want different images for Normal vs. Selected/Highlighted. The button style is what you set to UIButtonStyleCustom, I believe - again, look at the docs for the style property on UIButton.Ganiats
Isn't adding a UIButton on top of the UIImageView a little over the top? You're adding an extra object, whereas you could just implement the touches methods of the already existing UIImageView object. No?Pecoraro
If you look at the size of a UIButton in memory, it's virtually nothing and you only have a few per screen. What you get for free is the whole target action wiring for different states (like touch up inside) and also nice behavior like not triggering when you press down but slide a finger to the side. Basically buttons are one of the most finely crafted objects in the whole system and to think you are going to do custom touch code that works better is madness. Use that which is cheap and works well, save the custom work for things that the frameworks don't already handle for you.Ganiats
You can also overlay a UIControl if all you need are touch events (via addTaget:action:forControlEvents:). It's a bit cheaper than a UIButton which has images and several states. Also, I use preprocessor conditionals to change the overlayed control's background color to pink so I can see exactly where they are (and remember that they exist :-).Hager
W
115

A UIImageView is derived from a UIView which is derived from UIResponder so it's ready to handle touch events. You'll want to provide the touchesBegan, touchesMoved, and touchesEnded methods and they'll get called if the user taps the image. If all you want is a tap event, it's easier to just use a custom button with the image set as the button image. But if you want finer-grain control over taps, moves, etc. this is the way to go.

You'll also want to look at a few more things:

  • Override canBecomeFirstResponder and return YES to indicate that the view can become the focus of touch events (the default is NO).

  • Set the userInteractionEnabled property to YES. The default for UIViews is YES, but for UIImageViews is NO so you have to explicitly turn it on.

  • If you want to respond to multi-touch events (i.e. pinch, zoom, etc) you'll want to set multipleTouchEnabled to YES.

Wineshop answered 13/5, 2009 at 1:32 Comment(2)
I tried that but never the less I don't receive the touchesBegan events... why is that?Equestrian
@Markus: I had the same problem, but fixed it by setting userInteractionEnabled to YES on my parent view. See #5887805Evslin
M
51

To add a touch event to a UIImageView, use the following in your .m file:

UITapGestureRecognizer *newTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myTapMethod)];

[myImageView setUserInteractionEnabled:YES];

[myImageView addGestureRecognizer:newTap];


-(void)myTapMethod{
    // Treat image tap
}
Minicam answered 15/7, 2013 at 20:33 Comment(1)
userInteractionEnabled = true is the part that is easy to forget, thanks.Eyeleteer
P
23

You can also add a UIGestureRecognizer. It does not require you to add an additional element in your view hierarchy, but still provides you will all the nicely written code for handling touch events with a fairly simple interface:

    UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleSwipe:)];
    swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
    [imgView_ addGestureRecognizer:swipeRight];        
    [swipeRight release];
    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleSwipe:)];
    swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [imgView_ addGestureRecognizer:swipeLeft];
    [swipeLeft release];
Prizewinner answered 9/8, 2011 at 14:0 Comment(1)
DO NOT forget to set UserInteractionEnabled for the imgView_Yawl
P
13

I've been on different threads on the past few hours trying to find a solution for my problem, to no avail. I see that many developers share this problem, and I think people here know about this. I have multiple images inside a UIScrollView, trying to get tap events on them.

I am not getting any events from an UIImangeView, but I do get an event from a similar UILable with very similar parameters I am setting to it. Under iOS 5.1.

I have already done the following:

  1. set setUserInteractionEnabled to YES for both `UIImageView and parent view .
  2. set setMultipleTouchEnabled to YES for UIImageView.
  3. Tried subclassing UIImageView, didn't help any.

Attaching some code below, in this code I initialize both a UIImageView and UILabel, the label works fine in terms of firing events. I tried keeping out irrelevant code.

UIImageView *single_view = [[UIImageView alloc]initWithFrame:CGRectMake(200, 200, 100, 100)];
single_view.image = img;
single_view.layer.zPosition = 4;

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureCaptured:)];
[single_view addGestureRecognizer:singleTap];
[single_view setMultipleTouchEnabled:YES];
[single_view setUserInteractionEnabled:YES];
[self.myScrollView addSubview:single_view];
self.myScrollView.userInteractionEnabled = YES;

UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
testLabel.backgroundColor = [UIColor redColor];
[self.myScrollView addSubview:testLabel];
[testLabel addGestureRecognizer:singleTap];
[testLabel setMultipleTouchEnabled:YES];
[testLabel setUserInteractionEnabled:YES];
testLabel.layer.zPosition = 4;

And the method which handles the event:

- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
    UIView *tappedView = [gesture.view hitTest:[gesture locationInView:gesture.view] withEvent:nil];
    NSLog(@"Touch event on view: %@", [tappedView class]);
}

As said, the label tap is received.

Prokofiev answered 23/7, 2012 at 10:15 Comment(0)
E
6

Instead of making a touchable UIImageView then placing it on the navbar, you should just create a UIBarButtonItem, which you make out of a UIImageView.

First make the image view:

UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"nameOfYourImage.png"]];

Then make the barbutton item out of your image view:

UIBarButtonItem *yourBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:yourImageView];

Then add the bar button item to your navigation bar:

self.navigationItem.rightBarButtonItem = yourBarButtonItem;

Remember that this code goes into the view controller which is inside a navigation controller viewcontroller array. So basically, this "touchable image-looking bar button item" will only appear in the navigation bar when this view controller when it's being shown. When you push another view controller, this navigation bar button item will disappear.

Ezaria answered 23/4, 2010 at 5:31 Comment(0)
M
3

You might want to override the touchesBegan:withEvent: method of the UIView (or subclass) that contains your UIImageView subview.

Within this method, test if any of the UITouch touches fall inside the bounds of the UIImageView instance (let's say it is called imageView).

That is, does the CGPoint element [touch locationInView] intersect with with the CGRect element [imageView bounds]? Look into the function CGRectContainsPoint to run this test.

Mccauley answered 12/5, 2009 at 23:32 Comment(2)
Thanks for your reply. I have added the view like this: [navBar addSubview:self.pImage]; // added as a subview of the navigation bar. I have overriden the function but the function is never called. I have set the property userInteractionEnabled of the UIImageView to YES though. Am I missing anything?Clairclairaudience
Check out the touchesBegan:withEvent: method. There are plenty of examples on search engines of how this works.Mccauley
H
2

First, you should place an UIButton and then either you can add a background image for this button, or you need to place an UIImageView over the button.

Or:

You can add the tap gesture to a UIImageView so that get the click action when tap on the UIImageView.

Hiles answered 14/7, 2015 at 5:16 Comment(0)
B
0

For those of you looking for a Swift 4 solution to this answer, you can use the following to detect a touch event on a UIImageView.

let gestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageViewTapped))
imageView.addGestureRecognizer(gestureRecognizer)
imageView.isUserInteractionEnabled = true

You will then need to define your selector as follows:

@objc func imageViewTapped() {
    // Image has been tapped
}
Byelostok answered 24/4, 2018 at 10:7 Comment(0)
G
-2

Add gesture on that view. Add an image into that view, and then it would be detecting a gesture on the image too. You could try with the delegate method of the touch event. Then in that case it also might be detecting.

Griqua answered 25/7, 2012 at 9:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.