iOS - UITableViewCell 中 UIButton 的“Touch Down”延迟事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22924817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS - Delayed "Touch Down" event for UIButton in UITableViewCell
提问by Birrel
I have a custom UITableViewCell, which is initialized by the following:
我有一个自定义的 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;
}
The button appears properly, with the appropriate background image, but the highlighted image does not instantlyappear when the button is pressed/clicked. Instead, you have to hold it down for a second or two before the change occurs. Releasing the button, on the other hand, does have an instantchange back to the original background image.
按钮显示正确,具有适当的背景图像,但在按下/单击按钮时不会立即显示突出显示的图像。相反,您必须在更改发生之前按住它一两秒钟。另一方面,释放按钮确实会立即变回原始背景图像。
Trying to mitigate the tardy change when switching to the highlighted image, I put the change in the following method:
尝试在切换到突出显示的图像时减轻延迟更改,我将更改放在以下方法中:
- (IBAction)downDown:(id)sender {
[self.downButton setBackgroundColor:[UIColor redColor]];
}
The method above is set for "Touch Down" (opposed to the more common "Touch Up Inside"), and I have removed the setBackgroundImage:forState:
for the highlighted state. Same problem as mentioned above. The color does eventuallychange to red, but only after clicking and holding on the button for a second or two.
上面的方法设置为“Touch Down”(与更常见的“Touch Up Inside”相反),并且我已经删除setBackgroundImage:forState:
了突出显示状态。和上面提到的问题一样。颜色最终会变为红色,但只有在单击并按住按钮一两秒钟后才会变为红色。
I have a method for the button that is called when "Touch Up Inside" occurs, and that method executes without issue - regardless of whether I quickly tap the button, or click and hold on it for a length of time before releasing.
我有一个在“Touch Up Inside”发生时调用的按钮方法,并且该方法执行没有问题 - 无论我是快速点击按钮,还是在释放之前单击并按住它一段时间。
So why the delay for the "Touch Down" or UIControlStateHighlighted
? I'm trying to provide instant feedback to the user to show that the button has been pressed.
那么为什么延迟“触地”或UIControlStateHighlighted
?我正在尝试向用户提供即时反馈以显示按钮已被按下。
I can provide more code if needed, but these are the only bits that have anything to do with the background appearance.
如果需要,我可以提供更多代码,但这些是与背景外观有关的唯一部分。
回答by Dima
This is caused by the UIScrollView
property delaysContentTouches
.
这是UIScrollView
属性造成的delaysContentTouches
。
It used to be sufficient to just set that property to NO
for the UITableView
itself, but that will only work for subviews of the table that are not encased in another UIScrollView
.
过去,只需将该属性设置NO
为UITableView
本身就足够了,但这仅适用于未包含在另一个UIScrollView
.
UITableViewCells
contain an internal scroll view in iOS 7 so you will need to change the value of this property on the cell level for all cells with buttons in them.
UITableViewCells
在 iOS 7 中包含一个内部滚动视图,因此您需要在单元格级别为所有带有按钮的单元格更改此属性的值。
Here is what you need to do:
以下是您需要做的:
1.in viewDidLoad
or somewhere similar once your UITableView
has been initialized, put this in:
1.在初始化后viewDidLoad
或类似的地方UITableView
,将其放入:
self.tableView.delaysContentTouches = NO;
2.for iOS 7 support, in the initialization method for your UITableViewCell
(initWithStyle:reuseIdentifier:
or initWithCoder:
for NIBs), put this in at the end:
2.对于iOS 7支持,在你的UITableViewCell
(initWithStyle:reuseIdentifier:
或initWithCoder:
NIBs)的初始化方法中,把这个放在最后:
for (UIView *currentView in self.subviews)
{
if([currentView isKindOfClass:[UIScrollView class]])
{
((UIScrollView *)currentView).delaysContentTouches = NO;
break;
}
}
This is unfortunately not a 100% permanent solution as Apple can change the view hierarchy inside cells again in the future (perhaps moving the scroll view another layer down or something which would require you to nest another loop in there), but until they surface the class or at least the property to developers somehow, this is the best we've got.
不幸的是,这不是 100% 永久的解决方案,因为 Apple 可以在将来再次更改单元格内的视图层次结构(也许将滚动视图向下移动另一层或需要您在其中嵌套另一个循环的内容),但直到它们浮出水面以某种方式向开发人员提供类或至少属性,这是我们所拥有的最好的。
回答by Nitin Nain
Swift 3solution (for iOS8+):
Swift 3解决方案(适用于 iOS8+):
Firstly, turn off delays in UITableView
after it is loaded successfully, for example, inside viewDidLoad()
method:
首先,在UITableView
加载成功后关闭延迟,例如insideviewDidLoad()
方法:
someTableView.delaysContentTouches = false
Then turn off delays in the scroll views contained inside the UITableView
:
然后关闭包含在以下内容中的滚动视图中的延迟UITableView
:
for case let scrollView as UIScrollView in someTableView.subviews {
scrollView.delaysContentTouches = false
}
Note for iOS7: You might have to disable the delays in UITableViewCell
. (Check Dima's answer).
iOS7 的注意事项:您可能必须禁用UITableViewCell
. (检查迪马的回答)。
You might also find some other tips here.
您还可以在此处找到一些其他提示。
回答by Alex
i solve this problem in my code by subclassing UIButton,
我通过继承 UIButton 在我的代码中解决了这个问题,
Objective C
目标 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
swift
迅速
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)
}
}
swift 3
迅捷 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)
}
}
回答by Marc
Swift 3 version of Alex's answer:
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)
}
回答by Sandy Chapman
Here's a recursive solution you can add to your view controller:
这是您可以添加到视图控制器的递归解决方案:
+ (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];
}
回答by Dmitry Isaev
So why the delay for the "Touch Down" or
UIControlStateHighlighted
? I'm trying to provide instant feedback to the user to show that the button has been pressed.
那么为什么延迟“触地”或
UIControlStateHighlighted
?我正在尝试向用户提供即时反馈以显示按钮已被按下。
Hasn't Apple explained it yet?
苹果还没有解释吗?
Without this delay:
没有这个延迟:
If you want to scroll the view, and your finger touches anything highlightable (e.g. any table cell with the default selection style), you get these blinking artifacts:
Really, they don't know on
touchDown
, whether you're going to tap or scroll.If you want to scroll the view, and your finger touches a
UIButton
/UITextField
, the view isn't scrolled at all! Button/TextField's default behavour is "stronger" than the scrollview's, it keeps waiting for atouchUpInside
event.
回答by Jonguo
Maybe this answer is more simple. just add an animation delay to it. like below:
也许这个答案更简单。只需为其添加动画延迟即可。像下面这样:
[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];