Magic Bullet Dave
Magic Bullet Dave

Reputation: 9076

UIButton state change does not happen till after touches end

Sorry if this is a basic question, I can't find a definitive answer.

I have set up 4 buttons:

// Add the normal and selected state for each button
UIImage *buttonImage =  [UIImage imageNamed:[NSString stringWithFormat:@"HotspotNumber2-%i.png",(hotspotID +1)]];
[hotspotButton setImage:buttonImage forState:UIControlStateNormal];
UIImage *buttonImageSelected =  [UIImage imageNamed:[NSString stringWithFormat:@"HotspotNumber2-%is.png",(hotspotID +1)]];
[hotspotButton setImage:buttonImageSelected forState:UIControlStateSelected];
[hotspotButton setImage:buttonImageSelected forState:UIControlStateHighlighted];
[hotspotButton addTarget:self action:@selector(hotspotTouch:) forControlEvents:UIControlEventTouchDown];

And I trap the touch events in the method:

// Called when a hotspot is touched
-(void)hotspotTouch:(id)sender{

    // Deselect the hotspot currently selected
    if (selectedHotspot) [selectedHotspot setSelected:NO];

    selectedHotspot = (UIButton *)sender;
    [selectedHotspot setSelected:YES];

    // Get dictionary of hot spot that is pressed
    NSDictionary *hotspot = [hotspots objectAtIndex:[selectedHotspot tag]];
    NSString *imageFileName = [hotspot objectForKey:ksHotspotItemKey];
    if ([imageFileName length] > 0) currentImageView.image = [UIImage imageNamed:imageFileName];
    }
}

The problem I have is that the highlighted image for the button does not display until the user releases their finger, which is a noticeable delay. I have seen others solve similar issues by changing the background image instead of the button state or performing a selector after a delay so the run loop gets chance to end. Both methods seem like hacks to me and would be grateful if someone could explain what is happening here and what the most robust way of achieving the effect that as soon as the user touches down on the button it changes to its highlighted state.

Thanks in advance,

Dave

Upvotes: 1

Views: 1501

Answers (1)

Magic Bullet Dave
Magic Bullet Dave

Reputation: 9076

Have found a work around. I have created one method for TouchDown and one for TouchUpInside and TouchUpOutside. The TouchDown simply deselects the button if it is already selected and changes my view's image. The TouchUp event sets the selected property of the button. As both the highlighted and selected images are the same the net effect is that the button changes as soon as the button is touched and remains that way after the touch up events. Code is here:

// Called when a hotspot is touched down
-(void)hotspotTouchDown:(id)sender{

    // Deselect the hotspot currently selected if it exists
    if (selectedHotspot) [selectedHotspot setSelected:NO];

    // Get dictionary of hot spot that is pressed
    NSDictionary *hotspot = [hotspots objectAtIndex:[sender tag]];

    // If the class of the hotspot is 'self' then replace the current image with a new one given in the hotspot data
    if ([[hotspot objectForKey:ksHotspotClassKey] isEqualToString:ksHotspotClassSelf]) {

        NSString *imageFileName = [hotspot objectForKey:ksHotspotItemKey];
        if ([imageFileName length] > 0) currentImageView.image = [UIImage imageNamed:imageFileName];
    }
}

// Called when a hotspot is touched up
-(void)hotspotTouchUp:(id)sender{
    // Set the selected property of the button
    selectedHotspot = (UIButton *)sender;
    [selectedHotspot setSelected:YES];
}

Upvotes: 1

Related Questions