Making an UIButton’s image tappable
In these days I’m developing again in Objective-C and yes, I have to admit, I’m a bit rusty.
Said this, the requirement I received is to create a sort of navigation bar where items
are UIButtons
. Each button is of type UIButtonTypeCustom
and it has a title and an image.
Ok. Easy for now. The code looks like the following.
UIImage* image = [UIImage imageNamed:@"my_image"]; [self.myButton setImage:image forState:UIControlStateNormal]; [self.myButton setTitle:@"My button" forState:UIControlStateNormal];
The “difficult” part is that both the button and the image need to be tappable. So, if I tap the image
a specific action, different from button one, is performed.
I racked my brain and I had a thought: subclassing UIButton
. Ok this could be a wonderful idea. But it’s not.
According to UIButton Edge Insets you should avoid to
subclass or reimplement UIButton
. In fact, as Richard Turton says
Not only is UIButton a class cluster, so not really suitable for subclassing, it also does a lot for you, and with judicious use of the image view, background image view and (as of iOS6) attributed titles, you can create almost any effect you want.
So, what’s the solution? A UIButton
has an imageView
property that wraps the image you have set with
setImage:forState:
method. Even if this property is read-only, as stated by Apple documentation,
you can attach a tap gesture and respond appropriately. For example.
UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewTapped:)]; tapGestureRecognizer.numberOfTapsRequired = 1; self.bindableButton.imageView.userInteractionEnabled = YES; [self.bindableButton.imageView addGestureRecognizer:tapGestureRecognizer];
Since image view objects are configured to disregard user events by default, you must
explicitly change the value of the userInteractionEnabled
property to YES
after initializing the object.
Now within imageViewTapped: method you can retrieve the button associated with the tapped image as follows:
[[tapGestureRecognizer view] superview];