88fsantos
88fsantos

Reputation: 393

IOS 5.1 drag and drop

I'm a noob on IOS. I have searched a lot, but I didn't find any good tutorial about Drag and Drop on IOS. I just read that is not directly supported. Is that possible to Drag an item from a scroll view to a view, and pass some information with it? Imagine the MAIL app. I want to drag an email to the big view on the right, and pass some information with it. Is there any book, or tutorial, that can teach me how to make it?

TKS!

Upvotes: 1

Views: 3902

Answers (1)

Rob
Rob

Reputation: 438232

It's just a matter of using Gesture Recognizers (see Event Handler Guide).

Actual implementations depends a little upon how you want to do it. Here's a random example where I've got a split view control and I'm dragging something from the tableview on the left into the view on the right, the whole drag and drop triggered by a long press (e.g. a "tap and hold"). Thus, I just create a gesture recognizer in the viewDidLoad of the tableview controller (in my case, the master view controller):

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.tableView addGestureRecognizer:longPress];

And then I defined a gesture recognizer handler that implements the drag and drop, e.g.,

- (IBAction)longPress:(UIGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateBegan)
    {        
        // figure out which item in the table was selected

        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[sender locationInView:self.tableView]];
        if (!indexPath)
        {
            inDrag = NO;
            return;
        }

        inDrag = YES;

        // get the text of the item to be dragged

        NSString *text = [NSString stringWithString:[[_objects objectAtIndex:indexPath.row] description]];

        // create item to be dragged, in this example, just a simple UILabel

        UIView *splitView = self.splitViewController.view;
        CGPoint point = [sender locationInView:splitView];
        UIFont *font = [UIFont systemFontOfSize:12];
        CGSize size = [text sizeWithFont:font];
        CGRect frame = CGRectMake(point.x - (size.width / 2.0), point.y - (size.height / 2.0), size.width, size.height);
        draggedView = [[UILabel alloc] initWithFrame:frame];
        [draggedView setFont:font];
        [draggedView setText:text];
        [draggedView setBackgroundColor:[UIColor clearColor]];

        // now add the item to the view

        [splitView addSubview:draggedView];
    }
    else if (sender.state == UIGestureRecognizerStateChanged && inDrag) 
    {
        // we dragged it, so let's update the coordinates of the dragged view

        UIView *splitView = self.splitViewController.view;
        CGPoint point = [sender locationInView:splitView];
        draggedView.center = point;
    }
    else if (sender.state == UIGestureRecognizerStateEnded && inDrag)
    {
        // we dropped, so remove it from the view

        [draggedView removeFromSuperview];

        // and let's figure out where we dropped it

        UIView *detailView = self.detailViewController.view;
        CGPoint point = [sender locationInView:detailView];

        UIAlertView *alert;
        if (CGRectContainsPoint(detailView.bounds, point))
            alert = [[UIAlertView alloc] initWithTitle:@"dropped in details view" message:nil delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        else
            alert = [[UIAlertView alloc] initWithTitle:@"dropped outside details view" message:nil delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
    }
}

Clearly, if you're dragging a subview from your scrollview, you'd replace the indexPathForRowAtPoint logic with something like:

    UIView *objectToDrag = nil;
    CGPoint point = [sender locationInView:myView];
    for (UIView *control in myView.subviews)
        if (CGRectContainsPoint(control.frame, point))
            objectToDrag = control;

    if (!objectToDrag)
    {
        inDrag = NO;
        return;
    }

That would help you identify what you want to drag, but from there, the logic is very similar (except, rather than dragging the UILabel as in my example, you'd drag your objectToDrag).

Upvotes: 4

Related Questions