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的支持,在你的UITableViewCell
( initWithStyle: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已被按下。
还没有苹果解释呢?
没有这个延迟:
-
如果你想滚动视图,并且你的手指接触到任何高亮的东西(例如任何具有默认select样式的表格单元格),你会得到这些闪烁的工件:
真的,他们不知道
touchDown
,你是否要点击或滚动。 -
如果你想滚动视图,并且你的手指触及一个
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];