3

I'm trying to set a UIButton's titleColor to a certain color when it is selected and when it is highlighted, however, I need to set the button to be selected when the user touches down on the UIButton.

I've set it up like so:

[button setTitleColor:normalColor forState:UIControlStateNormal];
[button setTitleColor:superDuperSpecialColor forState:UIControlStateHighlighted];
[button setTitleColor:superDuperSpecialColor forState:UIControlStateSelected];
[button addTarget:self 
           action:@selector(action:) 
 forControlEvents:UIControlEventTouchDown];

But when the button gets selected in the action: method using [senderButton setSelected:YES], it sets the titleColor to normalColor, rather than superDuperSpecialColor, which it should be, as it's both highlighted AND selected.

Commenting out the setSelected: call prevents the button from becoming and staying selected and commenting out the highlighted state color doesn't have any effect, it seems.

Will I have to add targets for UIControlEventTouchCancel, UIControlEventTouchUpInside and UIControlEventTouchUpOutside in order to call setSelected: after the highlight ends -or- change the titleColor for UIControlStateNormal to superDuperSpecialColor when the button gets a touch?

On a side note, I would have liked to set the titleColor like so:

[button setTitleColor:superDuperSpecialColor 
             forState:(UIControlStateHighlighted | UIControlStateSelected)];

But that doesn't seem to work. Why is that? Does Objective-C check for state equivalency?

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
RileyE
  • 10,874
  • 13
  • 63
  • 106
  • If it starts out normal color and setting selected make it normal also, are you sure anything is happening at all with the colors? – Marcus Adams Jul 24 '13 at 19:34
  • @MarcusAdams Setting it to selected sets it to `superDuperSpecialColor`, but it only shows that color AFTER the button is not highlighted, as the button becomes `selected` at the time of pressing down, which is the same as when the button highlights. – RileyE Jul 24 '13 at 19:36

3 Answers3

4

I verified your results, and it seems like a bug in iOS. It fails on both the simulator and the device (iOS 6.1). It seems like if the selected and highlighted states are both YES, then the selected settings should override the highlighted settings. It's mostly implemented that way. The button's text value works like this, but the color seems to get it wrong (defaults to normal).

You might want to try it against iOS 7 if you have the latest XCode to see if they've fixed this, otherwise report it as a bug.

Since selected isn't a commonly used state for a UIButton, it probably wasn't properly tested in combination with other states.

As a workaround, in your action method, you could set the color for the normal state to superDuperSpecialColor and add another action for the touch up events to set the normal color back to normal. Since the state while the button is pressed should never actually be normal, this won't break anything if they do fix it in the future.

Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
  • 1
    That's what I have ended up implementing, thank you. I also just tested it on iOS 7 and it seems to have the same results. I guess it's iOS that's messed up, in this case, and not my brain! – RileyE Jul 24 '13 at 20:23
1

For both selected and highlighted state it's also necessary to set title, while for only highlighted state title is taken from normal state. So, don't forget to add extra line:

[button setTitleColor:UIColor.blackColor forState:UIControlStateSelected];
[button setTitleColor:[UIColor.blackColor colorWithAlphaComponent:0.5f]
                 forState:UIControlStateSelected | UIControlStateHighlighted];

[button setTitle:@"Title" forState:UIControlStateSelected];
[button setTitle:@"Title" forState:UIControlStateSelected | UIControlStateHighlighted];

Сode below works fine without explicit setting title for highlighted state:

[button setTitleColor:UIColor.greyColor forState:UIControlStateNormal];
[button setTitleColor:[UIColor.greyColor colorWithAlphaComponent:0.5f]
             forState:UIControlStateHighlighted];

[button setTitle:@"Title" forState:UIControlStateNormal];
nemissm
  • 453
  • 6
  • 12
0

I think you need to check your UIButton type, in creation. I have code like this and works fine.

But setting state two states in one line doesn't work for me.

[button setTitleColor:superDuperSpecialColor 
             forState:(UIControlStateHighlighted | UIControlStateSelected)];
Alex Cio
  • 6,014
  • 5
  • 44
  • 74
Elto
  • 420
  • 3
  • 11
  • I'm using `[[UIButton alloc] initWithFrame:]`, so there isn't any type. – RileyE Jul 24 '13 at 19:19
  • Also, are you sure you're using `UIControlEventTouchDown` and then setting the `UIButton`'s `selected` property to `YES` within the method that is called upon touch down? – RileyE Jul 24 '13 at 19:20
  • My code, im initializing button with frame, testing with button created in storyboard too, all works. [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal ]; [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted ]; [button setTitleColor:[UIColor greenColor] forState:UIControlStateSelected ]; [button addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchDown]; // [button setSelected:YES]; -(void)action:(id)sender{ NSLog(@"sender"); [button setSelected:YES]; } – Elto Jul 24 '13 at 19:23
  • Well, that is exactly what I have, but my button reverts to the `UIControlStateNormal` color when the `[sender setSelected:YES]` (I'm assuming that's just a copy error you have in your comment) get's called. – RileyE Jul 24 '13 at 19:27