iosobjective-cuiimageviewdragtouches

How to Drag a UIImageView?


Here is my situation: I have 3 UIImageViews. Two of them will act as reactors (the ones that the third one would be dragged to). The third one, like mentioned, will be draggable to one of the two UIImageViews like mentioned before.

I am currently using the touchesBegan, touchesMoved, and touchesEnded to accomplish this, but there is one problem.

After the draggable UIImageView has been dragged to one of the two UIImageViews, I want the draggable image view to snap back slowly (animation) to the original position (bottom center).

How could I accomplish this? Thanks in advance!


Solution

  • I tried out in a miniproject to do dragging-snapping using the more convenient UIPanGestureRecognizer. Hope it could solve your problem, comment if you need more info (you can download the GitHub project from https://github.com/codedad/SO_Drag_n_Snap_iOS ).

    My ViewController.h:

    @interface ViewController : UIViewController <UIGestureRecognizerDelegate> {
        CGPoint firstPos;
    }
    
    @property IBOutlet UIImageView *spot1;
    @property IBOutlet UIImageView *spot2;
    @property IBOutlet UIImageView *bkgr;
    @property IBOutlet UIImageView *dragimg;
    
    - (float) distanceSquared:(CGPoint) p1 p2:(CGPoint) p2;
    - (IBAction)pan:(UIPanGestureRecognizer *)gesture;
    

    My ViewController.m:

    - (float) distanceSquared:(CGPoint) p1 p2:(CGPoint) p2 {
        float dx = (p1.x-p2.x);
        float dy = (p1.y-p2.y);
        return dx*dx+dy*dy;
    }
    
    void sort(int*a,int n,int*ndx) {
        int*b,*c,t;
        int*bi,*ci,ti;
        for(b=a+n,bi=ndx+n ; --b>a;) {
            --bi;
            for(c=b,ci=bi;--c>=a;) {
                --ci;
                if(*c>*b)t=*b,*b=*c,*c=t,ti=*bi,*bi=*ci,*ci=ti;
            }
        }
    }
    
    - (IBAction)pan:(UIPanGestureRecognizer *)gesture {
        CGPoint translatedPoint = [gesture translationInView:self.view];
    
        if ([gesture state] == UIGestureRecognizerStateBegan) {
            firstPos = [[gesture view] center];
        }
    
        translatedPoint = CGPointMake(firstPos.x+translatedPoint.x, firstPos.y+translatedPoint.y);
        [[gesture view] setCenter:translatedPoint];
    
        if ([gesture state] == UIGestureRecognizerStateEnded) {
            CGPoint snapPos;
            int distances[3];
            distances[0] = [self distanceSquared:dragimg.center p2:spot1.center];
            distances[1] = [self distanceSquared:dragimg.center p2:spot2.center];
            distances[2] = [self distanceSquared:dragimg.center p2:bkgr.center];
            int distances_ndx[3] = {0,1,2};
            sort(distances, 3, distances_ndx);
    
            switch (distances_ndx[0]) {
                case 0:
                    snapPos = spot1.center;
                    break;
                case 1:
                    snapPos = spot2.center;
                    break;
                default:
                    snapPos = bkgr.center;
                    break;
            }
            [UIView beginAnimations:nil context:NULL];
            [UIView setAnimationDuration:0.2];
            [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
            [UIView setAnimationDelegate:self];
            dragimg.center = snapPos;
            [UIView commitAnimations];
        }
    }
    

    my ViewController.xib:

    I included 4 UIImageViews. 3 of them are static (spot1,2 and the "home" spot background halftone circle), plus the draggable yellow circle inside the "home" spot. I also added a pan gesture recognizer. Then I set the outlets:

    enter image description here