Md1079
Md1079

Reputation: 1360

Track coordinates of UITableViewCell subview

I would like to fire an event when the subview of a UITableviewCell reaches a certain point on the screen, say for example when its origin.y reaches 44 points. It would also be nice to know if it was being scrolled up or down when it reached that point. I was playing with KVO on the frame of the subview but this seems fixed to the cell so no changes with that. Is this task possible?

Upvotes: 0

Views: 435

Answers (4)

bteapot
bteapot

Reputation: 2037

Vertical position of UITableViewCell is defined by its frame property, which represents position and size of that cell within its superview, UITableView. Typically, the frame property of the cell is changing only once for every time that UITableView requests a cell from its delegate for specific index path. That's it, UITableView gets a cell, places it in itself and that cell just lays there unchanged until rectangle stored in bounds property of UITableView ceases to include rectangle stored in the frame property of that cell. In that case UITableView marks that cell as hidden and places it into the pool of reusable cells.

Since the process of scrolling in essence is not a repositioning of subviews – it is merely a curious illusion of shifting a bounds viewport of UITableView – constant observing of UITableViewCell's properties are pointless.

Moreover, the frame property of subview of UITableViewCell also represents a position and size of that subview within its container, UITableViewCell. It is also will not change on scroll.

You need to observe changes in UITableView bounds property, which is also represented by contentOffset by the way. UITableView happens to be a subclass of UIScrollView, so you can use its delegate methods, such as -scrollViewDidScroll:, like in this simple example:


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

Upvotes: 2

Tejvansh
Tejvansh

Reputation: 676

Here's a simple approach, which you can use if you have only one section without section header.

Add this to your implementation:

CGFloat lastContentOffSet;

And then add this delegate method of scrollview as tableview is also a 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;
}

Change value of the cellheight according to your tableview cell and the distance of that subview with the cell.

Let me know if this code helped. :)

Upvotes: 1

Qazi
Qazi

Reputation: 381

Since I can not comment I am writing as an Answer

Changing the answer for the requirement.

Here is how I think it can be done, you need to have your custom UITableViewCell which has a function which can take in co-ordinates (again based on your logic if you just want an intersection where a cell just touches a boundary or if it has to be at a precise position in a frame), so your function would take the co-ordinates and will return a true and a false if it will tell you if the condition is met, and in your cellForTable function you call the function of UITableView cell to check if your condition is met, if it is in your view you create a subview at the exact location. You can also modify the function to return you the exact frame-cordinates so you can use them to create a subview\

Upvotes: 1

Mert Buran
Mert Buran

Reputation: 3017

Reach that subview of UITableViewCell with cellForRowAtIndexPath or tableView.visibleCells, then call convertRectToView: on that subview.

convertRectToView: allows you to do translations on different coordinate systems. For example, you can detect where that subview appears on screen by translating its frame within its superview into viewController.view

For more: Apple Documentation

Upvotes: 1

Related Questions