31

I thought to be clever and just put an transparent UIButton over an UIImageView with the exact frame size, so that I can wire it up easily with any event I like, for example TouchUpInside, and make it call a action method of an view controller when the user touches it. Well, it works until alpha is below 0.1f. If I do 0.01f, it will not work. So to get it work, when looking a long time on the screen, you'll see that 0.1f of alpha shining through. And that's totally disgusting ;)

It seems like iPhone OS trys to be clever and won't catch events on the button if it's visually not there. Any idea how to solve that?

Sure I could make a subclass of UIImageView and implement touchesBegan:... etc., but it doesn't feel really elegant. I mean...when I want to hyperlink an image on the web, I would never want create my own HTML element for that image, just to wire it up to an url when it's clicked. That just doesn't make a lot of sense to me.

Thanks
  • 40,109
  • 71
  • 208
  • 322

11 Answers11

46

You should be able to set the button's 'Type' to Custom in Interface Builder, and it will not display any text or graphical elements over the UIImageView. This way, you don't need to adjust the alpha. If the view is built from code, use:

button = [UIButton buttonWithType:UIButtonTypeCustom];
Jason
  • 28,040
  • 10
  • 64
  • 64
  • 1
    Perfect! I had UIButtonTypeRoundedRect. Now I don't need alpha. Great stuff! – Thanks May 27 '09 at 13:08
  • I get the following error when setting to UIButtonTypeCustom: "object cannot be set - either readonly property or no setter found" – Sheehan Alam Mar 17 '10 at 18:08
  • Updated answer; the property used to be readwrite back in 2009. – Jason Apr 11 '11 at 10:20
  • 2
    @Jason: The iOS SDK must have changed _again_, as I am able to set a button's type to Custom, and it works perfectly for this scenario -- the button displays no content (i.e. is invisible) and still captures events. – Alan Oct 24 '11 at 17:56
  • @Alan - just used this as well. Works great. – Joshua Dance Mar 05 '13 at 00:42
  • I get a breakpoint at this line of the appDelegate: [self.window makeKeyAndVisible]; ... What's the deal? – Morkrom May 06 '13 at 21:34
5

In addition to UIButtonTypeCustom, I set the button text colors to the following:

[button setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
[button setTitleShadowColor:[UIColor clearColor] forState:UIControlStateNormal];
[button setTitleColor:[UIColor clearColor] forState:UIControlStateHighlighted];
[button setTitleShadowColor:[UIColor clearColor] forState:UIControlStateHighlighted];
Echilon
  • 10,064
  • 33
  • 131
  • 217
David Green
  • 874
  • 7
  • 5
4

The best way of doing this is:

myButton.hidden = YES;

You can't use the buttonType property because it is a read only property. Only way to use it is when creating your button dynamically.

MrShoot
  • 843
  • 1
  • 9
  • 21
2

You can hide a button (or any object) and keep it active by adding a mask to its layer. The button will be invisible but will still catch events.

let layer = CAShapeLayer()
layer.frame = .zero
myButton.layer.mask = layer
Arnaud
  • 7,259
  • 10
  • 50
  • 71
2

i also beleive you can assign an image to a button.

The image can take up the entire frame and can also have no other artifacts of the buttone if you set it up right.

check out the Property

UIButtonInstance.currentImage

That way you are not hogging your resources with elements that are essentially already there.

Bluephlame
  • 3,901
  • 4
  • 35
  • 51
  • Would be an option too. I will try that. – Thanks May 27 '09 at 13:09
  • currentImage is readonly. But there is an [button setImage:image forState:UIControlStateNormal]; method. Only "bad" thing about it is, that it seems like if I had to provide an image for every state ;) ...maybe it will just pick that image for all states, if I dont provide another one. I'll try. – Thanks May 27 '09 at 13:14
0

This is what i did but with using a subclass of UIButton which i later found out should not be subclassed as per the net. My subclass was called Points

Points *mypoint=[Points buttonWithType:UIButtonTypeCustom];

then if you have an image you want to add to the button : [mypoint setImage:imageNamed:@"myimage"] forstate: UIControlStateNormal];

if you dont add this image then the button will be invisible to the user but should respond to touch. Thats how i created a hotspot on my imageView inorder to have it respond to user interaction.

j2emanue
  • 60,549
  • 65
  • 286
  • 456
0

It's the only way I found...

[yourButton setImage:[UIImage imageNamed:@"AnEmptyButtonWithTheSameSize.png"] forState:UIControlStateNormal];

Take care of the image. It must be .png

j0k
  • 22,600
  • 28
  • 79
  • 90
0

Custom UIButtons respond to user interactions unless their alpha is set to 0. Put a custom UIButton on top of your imageView and connect to buttonPressed action. I have also set an additional highlighted image for my UIView, now it really behaves like a UIButton. First I have defined a duration for the UIView for staying highlighted:

#define HIGHLIGHTED_DURATION 0.1 

Then set the image view highlighted if the button is pressed and start a timer to keep it highlighted for that duration. Do not forget to set the highlighted image for your imageview.

- (IBAction)buttonPressed:(id)sender {

[_yourImageView setHighlighted:YES];
_timer = [NSTimer scheduledTimerWithTimeInterval:HIGHLIGHTED_DURATION
                                          target:self
                                        selector:@selector(removeHighlighted)
                                        userInfo:nil
                                         repeats:NO];
}

And simply undo highlighting when the timer finishes:

-(void) removeHighlighted{
    _yourImageView.highlighted = NO;

}
Yunus Nedim Mehel
  • 12,089
  • 4
  • 50
  • 56
0

lazyImageView = [[UIImageView alloc] init];

                        button=[[UIButton alloc]init];
                        [UIButton buttonWithType:UIButtonTypeRoundedRect];
                        [button addTarget:self
                                   action:@selector(aMethodForVideo:)
                         forControlEvents:UIControlEventTouchUpInside];
                        [button setBackgroundImage:[UIImage    imageNamed:@"BackTransparent.png"] forState:UIControlStateHighlighted];
                        [button setTitle:@"" forState:UIControlStateNormal];

                                lazyImageView.frame=CGRectMake(x, y, w, h);
                                button.frame=CGRectMake(x, y, w, h);

Set frame of button and Image both have same frame .I use this code and working fine.Also set button background image forState:UIControlStateHighlighted so when you click on that when you see the click effect.

Chetu
  • 428
  • 1
  • 7
  • 19
0

I managed to do it using the following code. If the iPad is landscape the button will be located in the top right of the screen.

    UIButton *adminButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    adminButton.frame = CGRectMake(974.0f, 0.0f, 50.0f, 50.0f);
    [adminButton setBackgroundColor:[UIColor clearColor]];
    [adminButton setTag:1];
    [adminButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:adminButton];

Pressing the 'adminButton' will run the following function:

- (void)buttonPressed:(id)sender  {

int buttonId = ((UIButton *)sender).tag;

  switch(buttonId) {
    case 1:
       NSLog (@"Admin button was pressed");
        break;
    case 2:
        //if there was a button with Tag 2 this will be called
        break;

    default:
        NSLog(@"Key pressed: %i", buttonId);
        break;
   }

}
r farnell
  • 71
  • 4
0

Jasons answer above is nearly correct, but setting the button type is not possible. So to programmatically create an empty button, use this code:

UIButton* myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame=frame;
[self.view addSubview:myButton];
Blitz
  • 5,521
  • 3
  • 35
  • 53