在 tableview 滚动时拦截 UITableView 中的 TouchUpInside 事件

Posted

技术标签:

【中文标题】在 tableview 滚动时拦截 UITableView 中的 TouchUpInside 事件【英文标题】:Intercept TouchUpInside event in UITableView while tableview scrolls 【发布时间】:2013-05-21 00:01:52 【问题描述】:

我正在构建一个 UITableView,它在 tableview 的部分标题中有一个按钮,因此当用户向下滚动屏幕时,该按钮被固定在屏幕顶部。

问题在于,当 UITableView 移动时,节标题按钮的触摸事件没有注册。如果 tableview 不滚动,按钮只会获取触摸事件。

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

    if (!_sectionHeaderView) 
        _sectionHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];

        UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
        backButton.frame = CGRectMake(0, 0, 50, 50);
        [backButton setImage:[UIImage imageNamed:@"upArrow"] forState:UIControlStateNormal];
        [backButton addTarget:self action:@selector(scrollToTop:) forControlEvents:UIControlEventTouchUpInside];
        [_sectionHeaderView addSubview:backButton];

    
    return _sectionHeaderView;

目前,发生的情况是: - 如果 tableview 没有滚动,按钮会按预期执行:点击它,按钮会获得 TouchUpInside 手势。 - 如果 tableview 正在滚动,则按钮不会获​​得 TouchUpInside 手势 - 相反,tableview 会停止在原地。

我尝试将 UITableView 子类化并查看 touchesBegan: 方法等,但没有成功。我看到了相同的模式:手势仅在 tableview 不移动时显示。

更新: 这不是可用性问题 - 虽然我无法显示我正在处理的设计的屏幕截图,但在部分标题中使用按钮和控件是一个有效的用例。

这里有一个简单的草图来解释原因:

【问题讨论】:

这会导致糟糕的用户体验,正如@Undo 已经提到的,我强烈建议不要这样做。 @Stunner 我已经用图片更新了问题,以阐明用户体验 啊,我明白了……现在更有意义了。 【参考方案1】:

想通了!您需要做的就是继承UITableView,并覆盖hitTest:withEvent:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

    if ([[super hitTest:point withEvent:event] isKindOfClass:[UIButton class]]) 
        UIButton *buttonThatWasTapped = (UIButton *)[super hitTest:point withEvent:event];
        [buttonThatWasTapped sendActionsForControlEvents:UIControlEventTouchUpInside];
    
        return [super hitTest:point withEvent:event];

以下是这段代码的作用:如果触摸了 tableview,并且触摸发生在 UIButton 的边界内,则 tableview 会将触摸事件转发给 UIButton。

这里有一个警告:触摸事件可能会多次发送到 UIButton(我看到每次触摸都会进行 3 次调用)。此代码足以满足我的需求,但如果您在应用中使用此代码,请注意该问题 - 您可能需要修改上述代码以解决此问题。

【讨论】:

【参考方案2】:

这是应该发生的。

用户已经习惯了这种行为——当他们看到他们想要触摸的东西时,它允许他们停止表格视图的滚动。

想象一下,我正在滚动一个表格以查找“独角兽”行,而我滚动的速度非常快(因为它是一张大桌子,我不确定独角兽在哪里)。当“独角兽”出现在我的视野中时,我会本能地停下桌子来选择它。

使用当前系统,我可以点击表格视图上的任意位置,它会停止。如果按照您的方式实现表格视图,我会点击“地下rockchucks”来停止表格,突然间我正在查看有关rockchucks的信息 - 我想要有关独角兽的信息。

我现在变成了一个心怀不满的用户,把你的应用退回给 Apple,然后拿回我的 0.99 美元。

您不希望用户这样做。

【讨论】:

这种设计没有 HIG 问题 - 我有一个 UITableView 部分,因此部分标题始终浮动在屏幕顶部。虽然我很欣赏这些反馈,但它不适用于我的设计。

以上是关于在 tableview 滚动时拦截 UITableView 中的 TouchUpInside 事件的主要内容,如果未能解决你的问题,请参考以下文章

tableView和scrollView滚动起冲突,tableview不能滚动

在 UITableView 中滚动时移除 UIView

iOS:滚动 UITableView 时应用程序崩溃/内存被填充

向上滚动 UITable 后的 Swift 5 调用函数

如何在 UITable 中实现 Instagram 评论的效果?

使用 sectionForSectionIndexTitle 在 UITableView 中快速滚动