跟踪UITableViewCell子视图的坐标

时间:2015-06-01 07:24:50

标签: ios uitableview

我想在UITableviewCell的子视图到达屏幕上的某个点时触发一个事件,例如当它的origin.y达到44点时。当它到达那个点时,知道它是向上还是向下滚动也是很好的。我在子视图的框架上玩KVO,但这似乎固定在单元格上,因此没有变化。这个任务可以吗?

4 个答案:

答案 0 :(得分:2)

UITableViewCell的垂直位置由其frame属性定义,该属性表示其超级视图UITableView中该单元格的位置和大小。通常,每次UITableView从其委托请求特定索引路径的单元格时,单元格的frame属性只会更改一次。就是这样,UITableView获取一个单元格,将其置于其中并且该单元格保持不变,直到存储在UITableView的bounds属性中的矩形不再包含存储在该frame属性中的矩形。细胞。在这种情况下,UITableView将该单元格标记为隐藏,并将其放入可重用单元池中。

由于滚动过程本质上不是子视图的重新定位 - 它只是转移UITableView的bounds视口的奇怪错觉 - 不断观察UITableViewCell的属性是毫无意义的。

此外,UITableViewCell的子视图的frame属性也表示其容器UITableViewCell中该子视图的位置和大小。滚动时它也不会改变。

您需要观察UITableView bounds属性中的更改,顺便提一下,该属性也由contentOffset表示。 UITableView恰好是UIScrollView的子类,因此您可以使用其委托方法,例如-scrollViewDidScroll:,就像在这个简单示例中一样:

Illustration

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    UITableView *tableView = (UITableView *)scrollView;

    // current position
    CGFloat currentY = tableView.bounds.origin.y;

    // current inset
    CGFloat currentInset = tableView.contentInset.top;

    // trigger line position
    CGFloat triggerY = currentInset + currentY + kYourTriggerPosition;

    // nice visual mark
    UIView *line = [tableView viewWithTag:88];

    if (!line) {
        line = [[UIView alloc] initWithFrame:CGRectZero];
        line.tag = 88;
        line.backgroundColor = [UIColor redColor];
        [tableView addSubview:line];
    }

    line.frame = CGRectMake(0, triggerY, tableView.bounds.size.width, 1);

    // determine scroll direction
    BOOL scrollingUp = currentY > self.previousY;

    // all visible cells
    NSArray *visibleCells = tableView.visibleCells;

    [visibleCells enumerateObjectsUsingBlock:^(UITableViewCell *cell, NSUInteger idx, BOOL *stop) {

        // subview
        UIView *subview = [cell viewWithTag:kYourSubviewTag];

        // subview frame rect in UITableView bounds
        CGRect subviewRect = [subview convertRect:subview.frame toView:tableView];

        // trigger line within subview?
        BOOL triggered = (CGRectGetMinY(subviewRect) <= triggerY) && (CGRectGetMaxY(subviewRect) >= triggerY);

        if (triggered) {
            NSIndexPath *indexPath = [tableView indexPathForCell:cell];
            NSLog(@"moving %@, triggered for cell at [%2d:%2d]", @[@"down", @"up"][scrollingUp], indexPath.section, indexPath.row);
            [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
        }
    }];

    // save current position for future use
    self.previousY = currentY;
}

答案 1 :(得分:1)

因为我不能发表评论我写的是答案

更改要求的答案。

以下是我认为可以做到的,你需要让你的自定义UITableViewCell具有可以采取坐标的功能(如果你只是想要一个单元格的交叉点,那么再次基于你的逻辑只是接触一个边界或者如果它必须处于框架中的精确位置),那么你的函数将采用坐标并且如果它会告诉你条件是否满足,将返回true和false,并在你的cellForTable函数调用UITableView单元格的功能来检查您的条件是否得到满足,如果您在视图中,则在确切的位置创建子视图。您还可以修改该函数以返回确切的frame-cordinates,以便您可以使用它们来创建子视图\

答案 2 :(得分:1)

使用subviewUITableViewCellcellForRowAtIndexPath tableView.visibleCells联系,然后在convertRectToView:上致电subview

convertRectToView:允许您在不同的坐标系上进行翻译。例如,您可以通过将subview内的frame翻译为superview

来检测viewController.view在屏幕上的显示位置

更多信息:Apple Documentation

答案 3 :(得分:1)

这是一个简单的方法,如果您只有一个没有节标题的节,则可以使用它。

将此添加到您的实施中:

CGFloat lastContentOffSet;

然后添加scrollview的委托方法,因为tableview也是一个scrollview。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat cellHeight = 50;
    CGFloat touchingPoint = 44.0f;
    NSInteger rowNo = floor(scrollView.contentOffset.y / cellHeight);

    NSInteger startPoint = (rowNo * cellHeight);

    if (scrollView.contentOffset.y > lastContentOffSet) {
        NSLog(@"Row %ld scrolled down", (long)rowNo);
        if (scrollView.contentOffset.y > startPoint + touchingPoint) {
            // Do something here
            NSLog(@"Do something here");
        }
    }
    else {
        NSLog(@"Row %ld scrolled up", (long)rowNo);
        if (scrollView.contentOffset.y > startPoint + touchingPoint) {
            // Do something here
            NSLog(@"Do something here");
        }
    }
    lastContentOffSet = scrollView.contentOffset.y;
}

根据您的tableview单元格更改cellheight的值以及该子视图与单元格的距离。

如果此代码有帮助,请告诉我。 :)