5

I'm trying to drag an image and let it return to it's original position after releasing it. So far, I can drag an image by creating it as a button using the following code: (as seen in the answer to this question: Basic Drag and Drop in iOS )

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];

And later I define:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    CGPoint point = [[[event allTouches] anyObject] locationInView:self.view];
    UIControl *control = sender;
    control.center = point;
}

How can I make it return to it's original position after releasing it ?, for starters I will save the position at which each image is supposed to return, but then, there is anyway to indicate an UIImage to go from it's current position and move to another one ?, or any other alterative solution ?

Community
  • 1
  • 1
José Joel.
  • 2,040
  • 6
  • 28
  • 46

5 Answers5

7

UIGestureRecognizer is recommended by Apple for recent iOSes. You can use it not only for UIButton, but also for UIView (especially UIImageView in your case), etc. So I would like to recommend it.

In the interface:

@interface TestDragViewController : UIViewController {
    IBOutlet UIImageView *dragImage;
    CGPoint originalCenter;
}

In viewDidLoad, plz remember to enable userInteraction:

- (void)viewDidLoad {
    [super viewDidLoad];


    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self 
                                                                                 action:@selector(dragGesture:)];
    [dragImage addGestureRecognizer:panGesture];
    [dragImage setUserInteractionEnabled:YES];
}

And in its selector, I just set animation to visualize the returning effect:

#pragma mark -
#pragma mark UIPanGestureRecognizer selector
- (void) dragGesture:(UIPanGestureRecognizer *) panGesture{
    CGPoint translation = [panGesture translationInView:self.view];

    switch (panGesture.state) {
        case UIGestureRecognizerStateBegan:{
            originalCenter = dragImage.center;
        }
            break;
        case UIGestureRecognizerStateChanged:{
            dragImage.center = CGPointMake(dragImage.center.x + translation.x,
                                           dragImage.center.y + translation.y);
        }
            break;
        case UIGestureRecognizerStateEnded:{            
            [UIView animateWithDuration:kImageReturnTime 
                             animations:^{
                                 dragImage.center = originalCenter;
                             }
                             completion:^(BOOL finished){
                                 NSLog(@"Returned");
                             }];
        }
            break;
        default:
            break;
    }

    [panGesture setTranslation:CGPointZero inView:self.view];
}

Cheers,

Tommy

Tommy
  • 7,400
  • 4
  • 30
  • 26
1

Define CGPoint Globally, or in .h file.

  CGPoint point;          

      UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
      [button addTarget:self action:@selector(imageTouch:withEvent:)forControlEvents:UIControlEventTouchDown];
      [button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
      [button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
      [self.view addSubview:button];

And later I define:

- (IBAction) imageMoved:(UIButton*) sender withEvent:(UIEvent *) event
 {
point = [[[event allTouches] anyObject] locationInView:self.view];
UIControl *control = sender;
control.center = point;
 [sender addTarget:self action:@selector(touches:withEvent:) forControlEvents:UIControlEventTouchUpInside];
}

-(void)touches:(UIButton *)button withEvent:(UIEvent *)event {

[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction animations:^{
     button.center = point;

 } completion:^(BOOL finished){
     if (finished) {
    // do anything yu want
   }

it works awesome cause i am using it in my project!

Steve
  • 1,022
  • 2
  • 9
  • 30
0

In the solution I linked to in the thread you are referring I have created a generic drag drop manager that takes care of the return of a dragged object to the original position (if released outside a known dropzone). Currently there is no animation in the solution, but you could combine some of the ideas presented above.

See the some how generic drag and drop solution in iOS

jeyben
  • 258
  • 2
  • 8
0

How about calling a selector on UIControlEventTouchUpInside and then in the selector, just set the frame of your button to a new x and y coordinate (the ones that you have saved).

Hetal Vora
  • 3,341
  • 2
  • 28
  • 53
  • Thanks. But that would move the UIButton to a new position instantly, right ?. If so, it's possible to command the UIButton to move from it's current position to the new one once the selector on UIControlEventTouchUpInside is call? – José Joel. Apr 11 '11 at 22:23
-1

You know what, I was just working on this yesterday, so here you go with a little bonus animation:

- (void)previewImageTouchUpInside:(UIButton*)aButton {
    if (!previewImageDragged) {
        [self selectPreviewImage:aButton];
        return;
}

    previewImageDragged = NO;

    // If user drag photo a little and then release, we'll still treat it as a tap
    //  instead of drag
    if ((originalPositionOfButton.x - aButton.center.x) * 
      (originalPositionOfButton.x - aButton.center.x) + 
      (originalPositionOfButton.y - aButton.center.y) * 
      (originalPositionOfButton.y - aButton.center.y) < 10) {
        aButton.center = originalPositionOfButton;
        [self selectPreviewImage:aButton];
        return;
    }

    [UIView animateWithDuration:0.5
        delay:0
        options:UIViewAnimationOptionCurveEaseOut |
        UIViewAnimationOptionAllowUserInteraction animations:^{
        aButton.center = originalPositionOfButton;
    } completion:nil];
}



- (void)previewImageDraggedInside:(UIButton*)aButton event:(UIEvent*)event {
    if (!previewImageDragged) {
        originalPositionOfButton = aButton.center;
        [self.view bringSubviewToFront:aButton];
        [self.view bringSubviewToFront:[self.view viewWithTag:CHOOSE_PHOTO_BUTTON_TAG]];
    }

    UITouch* touch = [[event allTouches] anyObject];

    previewImageDragged = YES;
    aButton.center = CGPointMake(aButton.center.x+[touch locationInView:self.view].x-
        [touch previousLocationInView:self.view].x, 
        aButton.center.y+[touch locationInView:self.view].y-
        [touch previousLocationInView:self.view].y);
}

It still has a few magic numbers and I haven't renamed the functions and variables to suit your example, but it should be clear. I also did the indentation here since I don't manually break long lines in my code.

Hwee-Boon Yar
  • 512
  • 3
  • 13