2

Pressing the button quickly and not holding for a short time, will not highlight the button. Different from a UIButton on a common UIView.

Like the head photo in official Twitter client got same issue.
Instagram client seems solved this, all buttons works fine.

Find same question here:
Why doesn't UIButton showsTouchWhenHighlighted work when the button is on a UITableViewCell?

But I still don't know how to fix it.

Community
  • 1
  • 1
Albert Chu
  • 243
  • 1
  • 11

1 Answers1

8

Well... a UITableView is a subclass of UIScrollView and the UIScrollView class is known to eat touches for it's own purpose.
When it realizes the touch was not meant for it, it passes it to it's immediate subview.
This feature is the delaysContentTouches property (which by default is YES).

Which is why, the UIButton shows it's highlighted state only after a extended touch because the touch event was with the UITableView for a short while until it determined whether the touch was meant for scrolling or swiping the cell and on realizing the touch was for neither, it immediately passes the touch event to the subView directly below it.

In case of a quick-tap, the button's highlighted state is bypassed due to this delay and the target selector method is called directly.


To show the highlighted state of the button in a UITableView (just as it would on a UIView) do:

For iOS7+:

In -viewDidLoad or anywhere appropriate do:

[yourTableViewObject setDelaysContentTouches:NO];

Also... The cell.subviews has a class UITableViewCellScrollView which apparently is another scrollView and we need to disable the delaysContentTouches property of this class as well.

So... in the -cellForRowAtIndexPath: method (just before return cell;) do:

NSArray *test = cell.subviews;
for (UIView *currentView in cell.subviews) {
    if ([NSStringFromClass([currentView class]) isEqualToString:@"UITableViewCellScrollView"]) {
        UIScrollView *svTemp = (UIScrollView *) currentView;
        [svTemp setDelaysContentTouches:NO];
        break;
    }
}

For iOS 6-:

In iOS6, the cell.subviews has a UITableViewCellContentView class which is not a scrollView subclass and so all it takes is setting one parameter for the tableView alone.

So, in -viewDidLoad or anywhere appropriate, this is all that you need:

[yourTableViewObject setDelaysContentTouches:NO];

PS: By doing this, it will mess up with the scrolling of the tableView so use your better judgement.

staticVoidMan
  • 19,275
  • 6
  • 69
  • 98
  • If I do setDelaysContentTouches to NO, when draging the button it won't scrolling. I still can't figure out how Instagram client fixed this. – Albert Chu Feb 12 '14 at 08:49
  • 2
    Solved this by http://stackoverflow.com/questions/17701323/uiscrollview-delayscontenttouches-issue , I subclassed UITableView, add touchesShouldCancelInContentView: method, and always returns YES. But only works fine when [myTableViewObject setDelaysContentTouches:NO] calls at where I alloc the tableView, not the UITableView subclass init Method. – Albert Chu Feb 12 '14 at 10:59
  • There's a TableView setting in Xcode's Interface Builder called "Cancelable Content Touches" You need to make sure it is enabled. When that's enabled it seems to work for me with iOS 7 and the code above. – Paul Solt Mar 14 '14 at 17:41