Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Drag & Drop for a View?

Tags:

ios

I'm learning iOS and I can't find how to add drag and drop behavior to a UIView.

I tried:

[_view addTarget:self action:@selector(moved:withEvent:) forControlEvents:UIControlEventTouchDragInside];

It says "no visible interface for UIView declares selector addTarget (etc)"

Also I tried adding a pan gesture recognizer but not sure if that's what I need

- (IBAction)test:(id)sender {
       NSLog(@"dfsdfsf");
  }

It's called, but don't know how to get the coordinates of the event. What't the standard, simple way in iOS to register a callback for move events / do drag and drop?

Thanks in advance.

like image 709
User Avatar asked Nov 12 '12 22:11

User


2 Answers

A UIPanGestureRecognizer is definitely the way to go. If you want the user to drag the view around, you'll need the “translation” (movement) of the gesture in the superview's coordinate system:

- (IBAction)panWasRecognized:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:_view.superview];

Once you have the translation, you can move (“drag”) the view by changing its center:

    CGPoint center = _view.center;
    center.x += translation.x;
    center.y += translation.y;
    _view.center = center;

Finally, you want to set the pan gesture recognizer's translation back to zero, so the next time you get the message, it only tells you how much the gesture has moved since the last message:

    [recognizer setTranslation:CGPointZero inView:_view.superview];
}

Here it is all together for easy copy/paste:

- (IBAction)panWasRecognized:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:_view.superview];

    CGPoint center = _view.center;
    center.x += translation.x;
    center.y += translation.y;
    _view.center = center;

    [recognizer setTranslation:CGPointZero inView:_view.superview];
}
like image 143
rob mayoff Avatar answered Oct 11 '22 02:10

rob mayoff


Start with touchesBegan, touchesMoved, touchesEnded. Override these in your UIView subclass and you'll be on your way to learning the event system. You can get the event coordinates like so:

- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
    float x = [[touches anyObject] locationInView:self].x;
    float y = [[touches anyObject] locationInView:self].y;
}

Then there's a ton of stuff for converting coordinates between different views and so on. Once you've understood that, you can work with the UIGestureRecognizer stuff you've already found which is what you need.

You are going to need a pan gesture recognizer to do drag/drop. You can use the locationInView: selector in UIPanGestureRecognizer to find out where you are at any given moment.

You add your gesture recognizer like so, not with the target-action stuff you were trying:

UIPanGestureRecognizer *dragDropRecog = [[UIPanGestureRecognizer alloc] initWithTarget:yourView action:@selector(thingDragged:)];
[yourView addGestureRecognizer:dragDropRecog];

Then you have to implement the selector thingDragged: in your view:

- (void) thingDragged:(UIPanGestureRecognizer *) gesture
{
    CGPoint location = [gesture locationInView:self];
    if ([gesture state] == UIGestureRecognizerStateBegan) {
        // Drag started
    } else if ([gesture state] == UIGestureRecognizerStateChanged) {
        // Drag moved
    } else if ([gesture state] == UIGestureRecognizerStateEnded) {
        // Drag completed
    }
}

You'll be translating the view being dragged in the changed bit, and handling the drop in the ended section.

like image 32
Tim Avatar answered Oct 11 '22 03:10

Tim