iOS - 延迟"触摸" UITutView在UITableViewCell中的事件

时间:2014-04-07 23:16:22

标签: ios objective-c uitableview uibutton

我有一个自定义的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;
}

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

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

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

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

我有一个按钮的方法,当“Touch Up Inside”出现时调用该按钮,该方法无任何问题地执行 - 无论我是否快速点击按钮,或者在释放之前点击并按住它一段时间

那么为什么延迟“Touch Down”或UIControlStateHighlighted?我正在尝试向用户提供即时反馈,以显示按钮已被按下。

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

7 个答案:

答案 0 :(得分:80)

这是由UIScrollView属性delaysContentTouches引起的。

过去只需将NO本身的属性设置为UITableView即可,但这仅适用于未包含在另一个UIScrollView中的表的子视图。

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

以下是您需要做的事情:

1.in viewDidLoad或在UITableView初始化后的某个地方,将其放入:

self.tableView.delaysContentTouches = NO;

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

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

遗憾的是,这不是一个100%永久性的解决方案,因为Apple可以在将来再次更改单元格内的视图层次结构(可能将滚动视图移动到另一层或者需要在其中嵌套另一个循环的东西),但直到他们以某种方式向开发人员展示了这个类或至少是属性,这是我们所拥有的最好的。

答案 1 :(得分:25)

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

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

someTableView.delaysContentTouches = false

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

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

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

您可能还会找到其他一些提示here

答案 2 :(得分: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

迅速

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

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 :(得分:4)

Swift 3版Alexanswer

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)
}

答案 4 :(得分:2)

这是一个可以添加到视图控制器的递归解决方案:

DatabaseError

答案 5 :(得分:1)

  

那么为什么延迟#34; Touch Down&#34;还是UIControlStateHighlighted?我试图向用户提供即时反馈,以显示按钮已被按下。

Hasn&Apple解释了吗?

没有这个延迟:

  1. 如果你想滚动视图,手指触摸任何可突出显示的东西(例如任何具有默认选择样式的表格单元格),你会得到这些闪烁的文物:

    enter image description here

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

  2. 如果您要滚动视图,手指触及UIButton / UITextField,则视图不会滚动!按钮/ TextField的默认行为是“更强”&#34;与滚动视图相比,它一直在等待touchUpInside事件。

答案 6 :(得分:-1)

也许这个答案更简单。只需添加一个动画延迟。如下所示:

    [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];