iOS – 延迟UITableViewCell中UIButton的“Touch Down”事件

我有一个自定义的UITableViewCell,它由以下初始化:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; self = [nibArray objectAtIndex:0]; [self setSelectionStyle:UITableViewCellSelectionStyleNone]; [self.downButton setBackgroundImage:[UIImage imageNamed:@"button"] forState:UIControlStateNormal]; [self.downButton setBackgroundImage:[UIImage imageNamed:@"buttonSelected"] forState:UIControlStateHighlighted]; } return self; } 

该button显示正确,具有适当的背景图像,但按下/单击button时突出显示的图像不会立即显示。 相反,在发生变化之前,您必须将其保持一两秒钟。 另一方面,释放button确实会立即改变回原始的背景图像。

尝试减less切换到突出显示的图像时的迟缓更改,我将更改以下面的方法:

 - (IBAction)downDown:(id)sender { [self.downButton setBackgroundColor:[UIColor redColor]]; } 

上面的方法设置为“Touch Down”(与更常见的“Touch Up Inside”相对),并且我已经移除了setBackgroundImage:forState:用于突出显示的状态。 同上面提到的问题。 颜色最终会变成红色,但只能在按住button一两秒钟之后。

我有一个button的方法,当“Touch Up Inside”发生时被调用,并且该方法执行没有问题 – 不pipe我是否快速点击button,或者在释放之前点击并按住一段时间。

那么为什么延迟“触摸”或UIControlStateHighlighted ? 我试图向用户提供即时反馈,以显示button已被按下。

如果需要,我可以提供更多的代码,但是这些是唯一与背景外观有关的部分。

这是由UIScrollView属性delaysContentTouches引起的。

过去只需将UITableView属性设置为NO就足够了,但这只适用于不包含在另一个UIScrollView中的表的子视图。

UITableViewCells在iOS 7中包含一个内部滚动视图,因此您需要在单元格级别上为其中包含button的所有单元格更改此属性的值。

这是你需要做的:

1.in viewDidLoad或者一旦你的UITableView被初始化了,就把它放在:

 self.tableView.delaysContentTouches = NO; 

2.对于iOS 7的支持,在你的UITableViewCellinitWithStyle:reuseIdentifier:initWithCoder: for NIBs)的初始化方法中,把它放在最后:

 for (UIView *currentView in self.subviews) { if([currentView isKindOfClass:[UIScrollView class]]) { ((UIScrollView *)currentView).delaysContentTouches = NO; break; } } 

不幸的是,这不是一个100%永久性的解决scheme,因为苹果公司可能会在将来再次改变单元格内的视图层次结构(也许将滚动视图移到另一层或者需要嵌套另一个循环的东西),但是直到他们类或至less是开发商的财产,这是我们得到的最好的。

Swift 3解决scheme(适用于iOS8 +):

首先在UITableView的延迟:

 someTableView.delaysContentTouches = false 

然后closuresUITableView包含的滚动视图的延迟:

 for case let scrollView as UIScrollView in someTableView.subviews { scrollView.delaysContentTouches = false } 

注意iOS7:您可能必须禁用UITableViewCells的延迟。 (检查迪玛的答案)。

你也可以在这里find一些其他的提示。

我通过inheritanceUIButton来解决这个问题,

目标C

 @interface TBButton : UIButton @end @implementation TBButton - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.highlighted = true; [super touchesBegan:touches withEvent:event]; } - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.highlighted = false; [super touchesEnded:touches withEvent:event]; } - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.highlighted = false; [super touchesCancelled:touches withEvent:event]; } @end 

迅速

 class TBButton: UIButton { override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { highlighted = true super.touchesBegan(touches, withEvent: event) } override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { highlighted = false super.touchesEnded(touches, withEvent: event) } override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) { highlighted = false super.touchesCancelled(touches, withEvent: event) } } 

迅速3

 class TBButton: UIButton { override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { isHighlighted = true super.touchesBegan(touches, with: event) } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { isHighlighted = false super.touchesEnded(touches, with: event) } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { isHighlighted = false super.touchesCancelled(touches, with: event) } } 

斯威夫特3版的亚历克斯的回答 :

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { isHighlighted = true super.touchesBegan(touches, with: event) } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { isHighlighted = false super.touchesEnded(touches, with: event) } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { isHighlighted = false super.touchesCancelled(touches, with: event) } 

以下是您可以添加到视图控制器的recursion解决scheme:

 + (void)disableDelayedTouches:(UIView*)view { for(UIView *currentView in view.subviews) { if([currentView isKindOfClass:[UIScrollView class]]) { ((UIScrollView *)currentView).delaysContentTouches = NO; } [self disableDelayedTouches:currentView]; } } - (void)viewDidLoad { [super viewDidLoad]; [self.class disableDelayedTouches:self.view]; } 

那么为什么延迟“触摸”或UIControlStateHighlighted ? 我试图向用户提供即时反馈,以显示button已被按下。

还没有苹果解释呢?

没有这个延迟:

  1. 如果你想滚动视图,并且你的手指接触到任何高亮的东西(例如任何具有默认select样式的表格单元格),你会得到这些闪烁的工件:

    在这里输入图像说明

    真的,他们不知道touchDown ,你是否要点击或滚动。

  2. 如果你想滚动视图,并且你的手指触及一个UIButton / UITextField ,视图就不会滚动 ! Button / TextField的默认行为比scrollview的“强”,它不断等待touchUpInside事件。

也许这个答案更简单。 只是给它添加一个animation延迟。 如下所示:

  [self.publishButton bk_addEventHandler:^(id sender) { @strongify(self); // reset to normal state with delay [UIView animateWithDuration:0.1 animations:^{ self.publishButton.backgroundColor = [UIColor whiteColor]; }]; } forControlEvents:UIControlEventTouchUpInside]; [self.publishButton bk_addEventHandler:^(id sender) { //Set your Image or color self.publishButton.backgroundColor = [UIColor redColor]; } forControlEvents:UIControlEventTouchDown];