iOS - UITutViewCell中UIButton的延迟"Touch Down"事件

Bir*_*rel 39 objective-c uibutton uitableview ios

我有一个自定义的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;
}
Run Code Online (Sandbox Code Playgroud)

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

在切换到突出显示的图像时尝试缓解迟到的变化,我将更改放在以下方法中:

- (IBAction)downDown:(id)sender {
    [self.downButton setBackgroundColor:[UIColor redColor]];
}
Run Code Online (Sandbox Code Playgroud)

上面的方法设置为"Touch Down"(与更常见的"Touch Up Inside"相对),我已经删除setBackgroundImage:forState:了突出显示的状态.与上述相同的问题.颜色最终会变为红色,但只有在单击并按住按钮一两秒后才会变亮.

我有一个按钮的方法,当"Touch Up Inside"出现时,该方法会执行,并且该方法可以毫无问题地执行 - 无论我是否快速点击按钮,或者在释放之前单击并按住它一段时间.

那么为什么延迟"触地"还是UIControlStateHighlighted?我正在尝试向用户提供即时反馈,以显示按钮已被按下.

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

Dim*_*ima 83

这是由UIScrollView财产造成的delaysContentTouches.

过去只需将该属性设置NOUITableView自身,但这仅适用于未包含在另一个中的表的子视图UIScrollView.

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

这是你需要做的:

1. 在初始化之后的viewDidLoad某个或类似地点UITableView,将其放入:

self.tableView.delaysContentTouches = NO;
Run Code Online (Sandbox Code Playgroud)

2.对于iOS 7支持,在您UITableViewCell(initWithStyle:reuseIdentifier:initWithCoder:NIB)的初始化方法中,将其放在最后:

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

遗憾的是,这不是一个100%永久的解决方案,因为Apple可以在将来再次更改单元格内的视图层次结构(可能将滚动视图向下移动另一层或者需要在其中嵌套另一个循环的东西),但直到它们浮出水面或者至少是开发商的财产,这是我们得到的最好的.

  • 没有必要知道单元格滚动视图的确切(私有)类名,只需使用`if([currentView isKindOfClass:[UIScrollView class]]){...}`,这对于`UIScrollView`的子类都是如此同样. (3认同)
  • 完善!我已经和我争斗很长一段时间了.一个人如何找到这些问题的具体解决方案!? (2认同)

Nit*_*ain 26

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

首先,在UITableView成功加载后关闭延迟,例如,在viewDidLoad()方法内:

someTableView.delaysContentTouches = false
Run Code Online (Sandbox Code Playgroud)

然后关闭包含在其中的滚动视图中的延迟UITableView:

for case let scrollView as UIScrollView in someTableView.subviews {
    scrollView.delaysContentTouches = false
}
Run Code Online (Sandbox Code Playgroud)

iOS7的注意事项:您可能必须禁用延迟UITableViewCell.(检查Dima的答案).

您可能还会在此处找到其他一些提示.


Ale*_*lex 20

我通过子类化UIButton在我的代码中解决了这个问题,

目标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
Run Code Online (Sandbox Code Playgroud)

迅速

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

迅捷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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是可接受的答案,因为它没有滚动视图的副作用. (4认同)