Question

I have a UIImageView that I am able to successfully move over top of a UITableView. Both views (i.e. the UIImageView, and the UITableView) are subviews of the parent view of the viewController. The UIImageView I am moving using a UIPanGestureRecognizer object which then calls the method panGestureDetected. My method for panGestureDetected looks like this:

- (void)panGestureDetected:(UIPanGestureRecognizer *)recognizer {

    _startLocation = [recognizer locationInView:_imageView];

    NSLog(@"The point is: %d", _startLocation);

    int selectedRow = [_table indexPathForSelectedRow].row;
    NSLog(@"The current row is: %d", selectedRow);

    CGPoint newCenter  = _imageView.center;

    newCenter.y = [recognizer locationInView:[_imageView superview]].y;
    _imageView.center = newCenter;


}

The user can drag the UIImageView up and down over top of the UITableView. However, what I would like to do is have the UIImageView "link" or "connect" with whichever UITableViewCell/row that the UIImageView is covering, or closest to. If the UIImageView is in between two rows, the UIImageView should move to whichever row it is closest to on its own. Here is an image of what I am talking about:

enter image description here

In this image, the UIImageView is closer to row 1 than row 2, so after the user removes his/her finger, the UIImageView will simply move up a little bit more, and cover up row 1, making row 1 the "active row" so to speak.

At the moment, the movement of my UIImageView, and my UITableView are completely independent of one another, but when it comes to this movement where the user is dragging the UIImageView, I want there to be a connection. Can anyone show me how to do this?

Was it helpful?

Solution

Use the UITableView method indexPathForRowAtPoint: to determine which row at which the user stopped moving the image. Then cellForRowAtIndexPath to get the cell, then the cell's center, then set the UIImageView center to the cell center. Something like:

NSIndexPath *indexPath = [myTableView indexPathForRowAtPoint:touchPoint];
UITableViewCell *cell = [myTableView cellForRowAtIndexPath:indexPath];
myUIImageView.center = cell.contentView.center;

You could also animate the last statement so it moves to over the cell smoothly rather than jumping. Something like:

[UIView animateWithDuration:0.25 animations:^{
    myUIImageView.center = cell.contentView.center;
}];

Inside of a gesture recognizer handler:

-(void)myGestureRecognizerHandler:(UIPanGestureRecognizer *)gestureRecognizer{

    CGPoint touchPoint = [gestureRecognizer locationInView:myTableView];

    NSIndexPath *indexPath;
    UITableViewCell *cell;

    switch ([gestureRecognizer state]) {
        case UIGestureRecognizerStateBegan:
        // Do stuff for UIGestureRecognizerStateBegan...

        case UIGestureRecognizerStateChanged:
        // Do stuff for UIGestureRecognizerStateChanged, e.g.,
            myUIImageView.center = touchPoint;

        case UIGestureRecognizerStateEnded:

            indexPath = [myTableView indexPathForRowAtPoint:touchPoint];
            cell = [myTableView cellForRowAtIndexPath:indexPath];
        {
            [UIView animateWithDuration:0.25f animations:^{
                myUIImageView.center = cell.contentView.center;
            }];
        }
            break;

        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateFailed:
        default:
        // Do stuff for cancelled/failed/...

            break;
    }
}

OTHER TIPS

You can use the following methods to help you out.

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath
- (NSArray *)indexPathsForRowsInRect:(CGRect)rect

basically, whenever you finish moving the imageview, I would recommend grabbing a cell with indexPathForRowAtPoint using the new center of your image view. Then you can grab the frame for that cell with rectForRowAtIndexPath and then center your imageView in that frame.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top