views:

399

answers:

2

I have an UIViewController which contains a UITableView (subclassed) and another UIView (subclassed). They are on the same hierarchy level but the UIView is added last so it is the frontmost. I overrid touchesBegan/Moved/Ended to intercept the Gestures from the top UIView: my goal is to get the selected UITableViewCell and, if double tapped, create an ImageView to be dragged around. I appear to get it done but now I cannot scroll the UITableView anymore, even though I forward the touch events. Here are the methods for the UIView:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"BO");
    UITouch * touch = [touches anyObject];

    CGPoint tPoint = [touch locationInView:self];
    InventoryViewController * invViewCont = self.viewController;
    UITableView * invTab = invViewCont.inventoryTableView;
    [invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow] 
                          animated:YES];
    NSArray * cells = [invTab visibleCells];
    BOOL found = NO;
    for (UITableViewCell * cell in cells)
    {
        if (CGRectContainsPoint(cell.frame, tPoint)) 
        {
            [cell touchesBegan:touches withEvent:event];
            found = YES;
            break;
        }
    }


    if (!found)
    {
        [invViewCont.inventoryTableView touchesBegan:touches withEvent:event];
    }
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"Mo");
        UITouch * touch = [touches anyObject];
        CGPoint tPoint = [touch locationInView:self];

        copyObj.center = tPoint;
        InventoryViewController * invViewCont = self.viewController;
        UITableView * invTab = invViewCont.inventoryTableView;

        [invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow] 
                              animated:YES];
        NSArray * cells = [invTab visibleCells];
        BOOL found = NO;
        for (UITableViewCell * cell in cells)
        {
            if (CGRectContainsPoint(cell.frame, tPoint)) 
            {
                [cell touchesMoved:touches withEvent:event];
                found = YES;
                break;
            }
        }

        if (!found)
        {
            [invViewCont.inventoryTableView touchesMoved:touches withEvent:event];
        }

    }

    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

        UITouch * touch = [touches anyObject];
        if ([touch tapCount] == 2) 
        {
            [self desubCopyView];
        }
        CGPoint tPoint = [touch locationInView:self];
        copyObj.center = tPoint;
        InventoryViewController * invViewCont = self.viewController;
        UITableView * invTab = invViewCont.inventoryTableView;
        [invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow] 
                              animated:YES];
        NSArray * cells = [invTab visibleCells];
        BOOL found = NO;
        for (UITableViewCell * cell in cells)
        {
            if (CGRectContainsPoint(cell.frame, tPoint)) 
            {
                [cell touchesEnded:touches withEvent:event];
                //[cell.imageView touchesEnded:touches withEvent:event];
                found = YES;
                break;
            }
        }
        if (!found)
        {
            [invViewCont.inventoryTableView touchesEnded:touches withEvent:event];
        }
    }

And here are those in the UITableViewCell

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch * touch = [touches anyObject];
    if ([touch tapCount] == 2) 
    {
        CGPoint tPoint = [touch locationInView:self]; 
        NSLog(@"CellX %lf CY %lf", tPoint.x, tPoint.y);

        UIGraphicsBeginImageContext(self.bounds.size);
        [self.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

        UIImageView * newView = [[UIImageView alloc] initWithImage:viewImage];
        [dragArea addSubview:newView];
        dragArea.copyObj = newView;
        [newView release];

        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.4];
        dragArea.copyObj.transform = CGAffineTransformMakeScale(1.3, 1.3);
        [UIView commitAnimations];
        tPoint = [self convertPoint:tPoint toView:dragArea];
        dragArea.copyObj.center = tPoint;
    }
    [super touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"MOV %@", self.imageView.image);
    [super touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"ENDED");
    [super touchesEnded:touches withEvent:event];
}

And in my UITableView I have simply:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"BEGTB");
    [super touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"MOVTB");
    [super touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"ENDTB");
    [super touchesEnded:touches withEvent:event];
}

I am surely missing something but I do not know what

A: 

I would highly recommend looking into UITapGestureRecognizer instead of handling the touchesX events yourself.

BarrettJ
After a double tap I need to recognize the user while he drags the new View I create, is that possibile with only that UIGestureRecognizer?
rano
I believe if you added a UIPanGestureRecognizer you'd be able to detect them dragging it around.
BarrettJ
On second reading I'm not sure what you want is achievable with the recognizers - is what you want to be the user taps once then on the second tap the user leaves their finger down and the imageview is created and dragged around or is it that the user double taps and then an image view is created and the third time the user puts their finger down is when the imageview would be dragged around?
BarrettJ
If it's the former, maybe on a single tap (with the UITapGestureRecognizer) add a UIPanGestureRecognizer in case the user taps a second time and tries to move the imageview (that you create when the pan gesture recognizers starts recognizing) and a timer to deactive the pan gesture recognizer after a certain amount of time (for the cases where the user just wanted a single tap).
BarrettJ
@BarrettJ I want that a single tap selects the row in the tableview as usual, a second tap creates the imageview and then without leaving the screen the user can drag it around. I already am able to do this with the code above. THe problem is: I am no more able to scroll the underlying tableview since tha frontmost uiview intercepts it all and it seems i can't forward it properly. The ultimate goal is in fact: with the dragged imageview to scroll on the table view and dropping it onto another row (imagine it like the editing mode, but resulting in the dropping onto a row)
rano
@BarrettJ: I tried the gesture recognizers with no luck, I posted quite a workaround as a solution
rano
A: 

I found a workaround for this, override the methods for touch gestures in my custom UITableView in order to make it scroll programMatically as I drag upon it an object. Here is the 'solution'.

I still believe there is another simpler way to do this but I did not find it, so posting this and marking it as an 'answer' might help someone else.

rano