Different images for highlighted UIButton state

Go To StackoverFlow.com

0


I need 2 different images for highlighted state for an UIButton.

I've these lines of code:

- (IBAction)buttonPressed:(id)sender
{
    UIImage *followImageHighlighted = [UIImage imageNamed:@"follow-hilite.png"];
    UIImage *unfollowImageHighlighted = [UIImage imageNamed:@"unfollow-hilite.png"];
    if ([sender isSelected]) {
        // set this image for the next time the button will pressed
        [sender setImage:unfollowImageHighlighted forState:UIControlStateHighlighted];
    } else {
        // set this image for the next time the button will pressed
        [sender setImage:followImageHighlighted forState:UIControlStateHighlighted];
    }
}

- (void)viewDidLoad
{
    // ...
    UIImage *followImage = [UIImage imageNamed:@"follow.png"];
    UIImage *unfollowImage = [UIImage imageNamed:@"unfollow.png"];
    [self.followButton setImage:followImage forState:UIControlStateNormal];
    [self.followButton setImage:unfollowImage forState:UIControlStateSelected];
}

The problem is that every time I press the button I see the highlighted image follow-hilite.png.

Can't I change the highlighted image for a button on the road?

I think this is a bad limitation because when the button is selected (thus, "Following") and an user press it, he see the default image, then when it touch up the image is that for selected state and when the network operation is completed then the button image switch correctly to the selected one.

Ideas?

EDIT

- (IBAction)followButtonTapped:(id)sender
{
    BOOL isFollowed = [sender isSelected];
    NSString *urlString = isFollowed ? kUnfollowURL : kFollowURL;
    // operation [...]
    [self.followButton setSelected:(isFollowed) ? NO : YES];
    self.user.followed = !isFollowed;
}

I explain better the problem:

  • button in default state: black text on white background
  • button in selected state: white text on black background

If the target user is not followed, the button is in default state and if I try to press it I see the correct highlighted image.

BUT if the target user is followed and the button is in selected state, if I try to press it (and hold the finger) I see the button with black text on white background. This is very ugly and this is my problem.

2012-04-03 21:49
by Fred Collins
I don't know what [sender isSelected] is, but it's only returning yes - CodaFi 2012-04-03 21:52
What does this mean: "if the target user is followed" - danh 2012-04-04 00:18
If the user the view is displaying is followed by me - Fred Collins 2012-04-04 00:22
That's great. That's the app condition I was looking for. Will edit my answer in a min - danh 2012-04-04 00:27
@danh I've solved, check my answer. Thank you anyway - Fred Collins 2012-04-04 00:31


1

I've solved with:

[myButton setImage:imageSelectedHover forState:(UIControlStateSelected | UIControlStateHighlighted)];

2012-04-04 00:30
by Fred Collins


1

The IBAction is an awkward (at best, or impossible) place to configure the control. There must be some condition in your app that triggers the requirement for the different highlighted image. Configure the button when you detect that condition.

Use the "pressed" callback for taking whatever action the app is supposed to take on the press.

2012-04-03 22:31
by danh
How can I configure the button? The condition is the user touch up inside the button - Fred Collins 2012-04-03 22:33
I'm looking for the condition that makes you want to have a different highlight image. The touch is what makes the button want to display it's current highlight image. The button will do that without your help. What you want to do is set the right one beforehand based on some application condition - danh 2012-04-03 22:42
@dahn yes but before I start this I thought was a classical scenario for iOS programmers. But it seems to have not solutions - Fred Collins 2012-04-03 22:55
It might be. My guess is that you have a follow and unfollow function, and you'd like the same button to perform both functions. That is very common. Let me know if that's the case, and I'll show you some code. (By the way, if that is the scenario, then the application condition I was looking for is whether the user is currently following something) - danh 2012-04-03 22:58
I've updated my question - Fred Collins 2012-04-03 23:44


1

Glad it works. You solved it by updating the application condition: self.user.followed. Now, to make it really right, try this:

- (IBAction)followButtonTapped:(id)sender
{
    NSString *urlString = self.user.followed? kUnfollowURL : kFollowURL;
    // operation [...]
    self.user.followed = !self.user.followed;
}

The state of your model is what matters here. The selected state of the button is more like a bool that was lying around where you are keeping a copy of the real following state.

2012-04-04 00:49
by danh
Thanks for your time danh - Fred Collins 2012-04-04 11:12


0

I think you need to cast sender to UIButton* before you try to modify anything important and work out your variables, because sender does not include a method or property called -isSelected. Try this instead:

- (IBAction)buttonPressed:(id)sender
{
    UIImage *followImageHighlighted = [UIImage imageNamed:@"follow-hilite.png"];
    UIImage *unfollowImageHighlighted = [UIImage imageNamed:@"unfollow-hilite.png"];
    if ([self isSelected]) {
        // set this image for the next time the button will pressed
        [(UIButton*)sender setImage:unfollowImageHighlighted forState:UIControlStateHighlighted];
    } else {
        // set this image for the next time the button will pressed
        [(UIButton*)sender setImage:followImageHighlighted forState:UIControlStateHighlighted];
    }
[self isSelected] = ![self isSelected];
}
2012-04-03 21:56
by CodaFi
The cast is correct style, but not going to make a difference - danh 2012-04-03 22:23
He's also not changing his isSelected var, and I think that's where his problem lies. That's why I added the last line - CodaFi 2012-04-03 22:24
The problem is that the selected state (and highlighted state, too) are fixed based on the control event triggering the action. For a given control event, the code will always run the same path. @Fred needs to determine an app condition that will make him want to change the image, and then change it then, before the press even begins - danh 2012-04-03 22:27
I think we are talking past each other here. @Fred here wants to change the image for the highlighted state on touchUpInside. It seems reasonable enough, why would you assume the property was immutable - CodaFi 2012-04-03 22:41
Not immutable, but two other problems (sorry, I am not articulate enough to make clear): (1) depending on the control event, it might be too late - e.g. on touchUpInside, the highlight has been displayed by the time you get the IBAction, and (2) the control event is going to cause the selected state to be some value, it will be the same value for a given IBAction. There's no point in branching off of it because the branch will always run the same way. i.e. put a break point in both branches of the conditional you supplied... I claim *(now less confidently) that you'll never hit one of them - danh 2012-04-03 22:52
Ads