160

I set an images for button's states Normal,Highlighted and Selected, but when the button in selected state and I press/highlight it I didn't see my highlighted image but just grayed picture. Is it possible to set an image for highlighted state when the button selected?

my code:

[button setImage:[UIImage imageNamed:@"normal.png"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"pressed.png"] forState:UIControlStateHighlighted];
[button setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];

when I do:

[button setSelected:YES];

and press the button, the "pressed.png" image doesn't select.

user478681
  • 8,330
  • 4
  • 26
  • 34

15 Answers15

234

I found the solution: need to add addition line

[button setImage:[UIImage imageNamed:@"pressed.png"] forState:UIControlStateSelected | UIControlStateHighlighted];
user478681
  • 8,330
  • 4
  • 26
  • 34
  • 5
    Any way to do this via interface builder? – Stephen Nov 15 '12 at 06:31
  • 6
    @stephen: Setting the "Background"(image) property of UIButton for different conditions of "StateConfig"(Default/Highlighted/Selected/Disabled) Property works for me. – Ajeet Dec 10 '12 at 16:58
  • 2
    Ajeet's solution did not work for me. I'd also like to know a way of doing that on IB – Lucas Jan 30 '13 at 21:52
  • 3
    Since you can't set this in IB, you can put this in your viewDidLoad method, and it'll be almost as good, since you can then change the image in IB and not have to worry about always updating the code to match. [button setImage:[button imageForState:UIControlStateHighlighted] forState:UIControlStateSelected | UIControlStateHighlighted]; – Dave Wood Feb 04 '13 at 00:51
  • 4
    You **Can** do this in IB. See screenshots in below answer! – Ríomhaire Jul 31 '13 at 10:24
  • 1
    This should work for you Awesome-o, did you add it as an extra line of code? You need to have both [button setImage:[UIImage imageNamed:@"pressed.png"] forState:UIControlStateHighlighted]; and [button setImage:[UIImage imageNamed:@"pressed.png"] forState:UIControlStateSelected | UIControlStateHighlighted]; – Rick van der Linde Mar 28 '14 at 10:28
  • Do I need to use the line of code posted in this answer and also set the image for all "simple" (non-`OR`ed) states in IB (Default, Selected, Highlighted)? – Nicolas Miari Oct 01 '15 at 01:26
  • Crazy. It really only worked when setting all three: `[button setImage: img forState: UIControlStateSelected | UIControlStateHighlighted];`, `[button setImage: img forState: UIControlStateSelected];` and `[button setImage: img forState: UIControlStateHighlighted];` – anneblue Oct 14 '15 at 14:38
  • I wondered [self.button isSelected]; is not working in Xcode 7.2 even i created IBAction and it alway gives me .any help? – Avijit Nagare Oct 10 '16 at 10:16
125

You can do this in Interface Builder.

Select the UIButton you wish to set in IB then go to the attributes inspector.

In the screen shots,I am using a custom button type , but that does not matter.

Custom Default

enter image description here

enter image description here

Ríomhaire
  • 3,084
  • 4
  • 25
  • 40
32

Swift 3

// Default state (previously `.Normal`)
button.setImage(UIImage(named: "image1"), for: [])

// Highlighted
button.setImage(UIImage(named: "image2"), for: .highlighted)

// Selected
button.setImage(UIImage(named: "image3"), for: .selected)

// Selected + Highlighted
button.setImage(UIImage(named: "image4"), for: [.selected, .highlighted])

To set the background image we can use setBackgroundImage(_:for:)

Swift 2.x

// Normal
button.setImage(UIImage(named: "image1"), forState: .Normal)

// Highlighted
button.setImage(UIImage(named: "image2"), forState: .Highlighted)

// Selected
button.setImage(UIImage(named: "image3"), forState: .Selected)

// Selected + Highlighted
button.setImage(UIImage(named: "image4"), forState: [.Selected, .Highlighted])
kvothe
  • 511
  • 1
  • 6
  • 8
  • The array version didn't work for me. (at least during `setImage`) – huggie Apr 25 '16 at 07:46
  • 1
    iOS 10 will dim your normal/selected images, which is nice and looks nice. If you set a selected,highlighted image, it won't automatically dim the latter. Which is a bummer. – snakeoil Dec 09 '16 at 19:35
29

I think most posters here miss the point completely. I had the same problem. The original question was about the Highlighted state of a Selected button (COMBINING BOTH STATES) which cannot be set in IB and falls back to Default state with some darkening going on. Only working solution as one post mentioned:

[button setImage:[UIImage imageNamed:@"pressed.png"] forState:UIControlStateSelected | UIControlStateHighlighted];
alghanor
  • 297
  • 3
  • 3
  • i know but i was somehow not allowed – alghanor Aug 08 '13 at 12:14
  • 1
    for some reason I still get the issue even if I set it as above. The only way for me to get a custom image for my control state is to set UIControlStateHighlighted only. – Julius Jan 18 '17 at 21:47
12

If you have a good reason to do that, this will do the trick

add these targets:

[button addTarget:self action:@selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(buttonTouchUp:) forControlEvents:UIControlEventTouchUpInside];


-(void)buttonTouchDown:(id)sender{
    UIButton *button=(UIButton *)sender;
    if(button.selected){
        [button setImage:[UIImage imageNamed:@"pressed.png"] forState:UIControlStateNormal];
    }
}

-(void)buttonTouchUp:(id)sender{
    UIButton *button=(UIButton *)sender;
    [button setImage:[UIImage imageNamed:@"normal.png"] forState:UIControlStateNormal];
}
Jorge
  • 2,056
  • 1
  • 16
  • 23
  • Thank for this, but actually it is too complicated) I'll expect that the button will work as described above – user478681 Apr 08 '11 at 09:42
7

In swift you can do:

button.setImage(UIImage(named: "selected"), 
                forState: UIControlState.selected.union(.highlighted))
iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
Roland Keesom
  • 8,180
  • 5
  • 45
  • 52
7

In Swift 3.x, you can set highlighted image when button is selected in the following way:

// Normal state
button.setImage(UIImage(named: "normalImage"), for: .normal) 

// Highlighted state (before button is selected)
button.setImage(UIImage(named: "pressedImage"), for: .highlighted)

// Selected state
button.setImage(UIImage(named: "selectedImage"), for:  .selected)

// Highlighted state (after button is selected)
button.setImage(UIImage(named: "pressedAfterBeingSelectedImage"), 
                for:  UIControlState.selected.union(.highlighted))
iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
Ashish Verma
  • 1,776
  • 1
  • 16
  • 27
3

In my case, I have to change the UIButton.Type from .custom to .system

And:

button.setImage(UIImage(named: "unchecked"), for: .normal)
button.setImage(UIImage(named: "checked"), for: [.selected, .highlighted])

When handling tapping:

button.isSelected = !button.isSelected

Tai Le
  • 8,530
  • 5
  • 41
  • 34
2

Correct me if I am wrong. By doing

   [button setSelected:YES];

you are clearly changing the state of the buttons as selected. So naturally by the code you have provided the image will that for the selected state in your case checked.png

visakh7
  • 26,380
  • 8
  • 55
  • 69
  • not fully understand what do you mean by "clearing changing the state...". this is very simple: I set the images for states described above, add target-action for this button and in method that process my action (control event UIControlEventTouchUpInside) I toggle selected state for the button [button setSelected:YES/NO]. And when the button currently in selected state and I press/highlight it, I see only grayed image, like there was no image setup for this state. – user478681 Apr 08 '11 at 09:01
  • I meant clearly there. Sorry for that. When you press the button first you are setting its state as selected, so that image will be displayed. So if you want to get only highlighted image make its state as highlighted. I am not sure though if I am getting you properly – visakh7 Apr 08 '11 at 09:05
  • When I press the button first I state it as highlighted and then when I release it the state will be selected (as I set it in my action method). Than I press it again (button already in selected state) and the state should be changed to highlighted and I should see the pressed.png image but I don't see it in this case. – user478681 Apr 08 '11 at 09:23
1

If someone's wondering how this works in Swift, here's my solution:

button.setImage("normal.png", forState: .Normal)
button.setImage("highlighted.png", forState: .Highlighted)
button.setImage("selected.png", forState: .Selected)

var selectedHighLightedStates: UIControlState = UIControlState.Highlighted
selectedHighLightedStates = selectedHighLightedStates.union(UIControlState.Selected)
button.setImage("selectedHighlighted.png", forState: selectedHighLightedStates)
basedgod
  • 2,517
  • 1
  • 17
  • 18
1

Swift 3+

button.setImage(UIImage(named: "selected_image"), for: [.selected, .highlighted])

OR

button.setImage(UIImage(named: "selected_image"), for: UIControlState.selected.union(.highlighted))

It means that the button current in selected state, then you touch it, show the highlight state.

yuanjilee
  • 429
  • 5
  • 16
0

I had problem setting imageView.highlighted = NO; (setting YES worked properly and the image changed to the highlighted one).

The solution was calling [imageView setHighlighted:NO];

Everything worked properly.

Michal
  • 15,429
  • 10
  • 73
  • 104
DrArt
  • 141
  • 1
  • 1
  • 6
0

Where you want to call from

[button addTarget:self action:@selector(test:) forControlEvents:UIControlEventTouchUpInside];

The method:

-(void)test:(id)sender{
    UIButton *button=(UIButton *)sender;
    if (_togon){
      [button setTitleColor:UIColorFromRGB(89,89, 89) forState:UIControlStateNormal];
      _togon=NO;
    }
    else{
      [button setTitleColor:UIColorFromRGB(28, 154, 214) forState:UIControlStateNormal];
      _togon=YES;
    }
}

Credit above to Jorge but I improved it a bit giving the full working solution

byJeevan
  • 3,728
  • 3
  • 37
  • 60
Kingsley Mitchell
  • 2,412
  • 2
  • 18
  • 25
0

Xamarin C#

Doing bitwise OR doesn't work for some reason

button.SetImage(new UIImage("ImageNormal"), UIControlState.Normal);
button.SetImage(new UIImage("ImagePressed"), UIControlState.Selected | UIControlState.Highlighted | UIControlState.Focused);

The following works

button.SetImage(new UIImage("ImageNormal"), UIControlState.Normal);
button.SetImage(new UIImage("ImagePressed"), UIControlState.Selected);
button.SetImage(new UIImage("ImagePressed"), UIControlState.Highlighted);
button.SetImage(new UIImage("ImagePressed"), UIControlState.Focused);
Pierre
  • 8,397
  • 4
  • 64
  • 80
0

If you need the highlighted tint which the OS provides by default when you tap and hold on a custom button for the selected state as well, use this UIButton subclass. Written in Swift 5:

import Foundation
import UIKit
class HighlightOnSelectCustomButton: UIButton {
    override var isHighlighted: Bool {
        didSet {
            if (self.isSelected != isHighlighted) {
                self.isHighlighted = self.isSelected
            }
        }
    }
}
Raj Pawan Gumdal
  • 7,390
  • 10
  • 60
  • 92