2

我正在构建一个 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: 方法等,但没有成功。我看到了相同的模式:手势仅在表格视图不移动时显示。

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

这是一个快速草图来解释原因:

浮动节标题

4

2 回答 2

6

弄清楚了!您需要做的就是子类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 次调用)。此代码足以满足我的需求,但如果您在应用程序中使用此代码,请注意该问题 - 您可能需要修改上述代码以解决此问题。

于 2013-05-21T20:00:41.920 回答
2

这是应该发生的事情。

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

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

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

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

您不希望用户这样做。

于 2013-05-21T00:07:15.167 回答