20

I have a UIButton subview inside of a UITableViewCell.

When this button is touched, the user must hold the button for about a half second for the button's image to change to the UIControlStateHighlighted image.

This means that if the user just taps the button as is usually the case, the highlighted state is never shown.

Why does this occur and how can I fix it?

5 Answers5

25

I just encountered this problem and saw that this issue hadn't been closed. After screwing around for a while I found a fix for it.

Now you can fix this by turning off delaysContentTouches or unchecking the "Delays content touches" box on the tableview.

The only negative side effect is that the user won't be able to tap down on a button and initiate a scrolling gesture. However, if the user tries to scroll starting from anywhere that doesn't itself accept touches, the behavior should be the same as before.

David Hodge
  • 1,724
  • 15
  • 13
11

Up for David Hodge's answer.

I just want to add a way to remove that "only negative side effect", already described by David: if you start scrolling inside a UIcontrol in a UIScrollView with delayContentTouches=NO, scrolling doesn't work.

SOLUTION Subclass UIScrollView (or UITableView as the original question) and override:

-(BOOL) touchesShouldCancelInContentView:(UIView *)view {   
return YES; 
}

Your UIControls inside UIScrollView/UITableView will change their state immediately on tap and the scrollviews will be able to scroll even if the touch starts on some UIControl. Works like a charm.

Donnit
  • 1,217
  • 12
  • 19
11

The problem is that your UIButton is inside a UITableView. This means that the table view has to determine whether your tap is going to be a swipe or if it's just a tap intended for the button. The table view has to delay sending a message to the UIButton until it knows that the user doesn't intend to swipe and therefore scroll the view instead of pressing the button.

If you don't need a table view, get rid of the UITableView.

lucius
  • 8,665
  • 3
  • 34
  • 41
3

I just change the image from within the target action method:

[sender setBackgroundImage:[UIImage imageNamed:@"highlighted-image.png"] forState:UIControlStateNormal];

It changes the background image instantly.

Michael Morrison
  • 1,323
  • 1
  • 18
  • 30
0

Edit: completely re-written following a misunderstanding of the question

One way of thinking of a UIButton is as a shorthand way of setting up an area of the screen that can respond to various instantaneous touch events the response it makes is defined by UIControl's Target-Action system for delivering messages to other objects.

UIControlEventTouchDown sounds like the one you need to respond to. It will be triggered as soon as someone touches inside your button - this is what the "Contact Info" button in SMS does.

UIButton* myButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect]; // SEt up title, frame etc [myButton addTarget:self action:@selector(myButtonWasPressed) forControlEvents: UIControlEventTouchDown]; [myMainView addSubView:myButton];

Will send a -(void)myButtonWasPressed message to the object this code runs from (ideally you view controller). In myButtonWasPressed you can then add a new view or take any action you like. The SMS app pushes a view controller to display the contact info using a navigation controller.

If this still doesn't solve your problem, you're going to have to post some code in order to get more insight into what's going wrong.

Rog
  • 17,070
  • 9
  • 50
  • 73
  • I think you misunderstand. If you look at the SMS app for instance, the icons at the top of a message thread react instantly to touches. I am saying that my buttons do not show an instant reaction to the highlighted state. I don't want the user to hold down a button. I want them to use a button normally but have the state of the button change and reflected in the button's visual appearance, as expected. –  Apr 26 '09 at 02:40
  • Okay there is still a misunderstanding :). There is nothing wrong with the actions or events of my button. To recreate what I am describing just create a new UITableViewCell, and add a UIButton as a subview of it: i.e. [cell.contentView addSubview:button]. Then test it on the device. When you touch the button, the action will fire correctly, however the button's highlighted status does not occur immediately. Rather, you have to hold the button down for half a second before you see the button *visually* change state. All I am talking about is the visual appearance of the button. –  Apr 28 '09 at 09:32