Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move a UIImageView with Touch

I'm trying to create moving functionality to my imageView (maskPreview in the code below), so that users can move a picture, which is contained in maskPreview, around the screen. Here's my code for touch begin and touch moved:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count]==1) {
    UITouch *touch= [touches anyObject];
    originalOrigin = [touch locationInView:maskPreview];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count]==1) {
    UITouch *touch = [touches anyObject];
    CGPoint lastTouch = [touch previousLocationInView:self.view];
    CGFloat movedDistanceX = originalOrigin.x-lastTouch.x;
    CGFloat movedDistanceY = originalOrigin.y-lastTouch.y;
    [maskPreview setFrame:CGRectMake(maskPreview.frame.origin.x+movedDistanceX, maskPreview.frame.origin.y + movedDistanceY, maskPreview.frame.size.width, maskPreview.frame.size.height)];
}
}

but I'm getting some weird responses from the app. I haven't put restrictions on how far the imageview can move, i.e. to prevent it from going out of the screen, but even if it's a small move, my imageview goes wild and disappears.

Thanks alot in advance for all the help

like image 291
Septronic Avatar asked Feb 03 '12 03:02

Septronic


2 Answers

Implementing touchesBegan and so on is way overkill in this modern world. You're just confusing the heck out of yourself, and your code will quickly become impossible to understand or maintain. Use a UIPanGestureRecognizer; that's what it's for. Making a view draggable with a UIPanGestureRecognizer is trivial. Here's the action handler for a UIPanGestureRecognizer that makes the view draggable:

- (void) dragging: (UIPanGestureRecognizer*) p {
    UIView* vv = p.view;
    if (p.state == UIGestureRecognizerStateBegan ||
        p.state == UIGestureRecognizerStateChanged) {
        CGPoint delta = [p translationInView: vv.superview];
        CGPoint c = vv.center;
        c.x += delta.x; c.y += delta.y;
        vv.center = c;
        [p setTranslation: CGPointZero inView: vv.superview];
    }
}
like image 181
matt Avatar answered Oct 04 '22 04:10

matt


There are two problems with your code. First, this line is wrong:

CGPoint lastTouch = [touch previousLocationInView:self.view];

It should be this:

CGPoint lastTouch = [touch previousLocationInView:maskPreview];

Really, you shouldn't even be using previousLocationInView:. You should just be using locationInView: like this:

CGPoint lastTouch = [touch locationInView:maskPreview];

Second, you are getting the signs of movedDistanceX and movedDistanceY wrong. Change them to this:

CGFloat movedDistanceX = lastTouch.x - originalOrigin.x;
CGFloat movedDistanceY = lastTouch.y - originalOrigin.y;

Also, the documentation for touchesBegan:withEvent: says this:

If you override this method without calling super (a common use pattern), you must also override the other methods for handling touch events, if only as stub (empy) implementations.

So make sure you're also overriding touchesEnded:withEvent: and touchesCancelled:withEvent:.

Anyway, you can do this quite a bit more simply. One way is to make touchesBegan:withEvent: empty and do all the work in touchesMoved:withEvent: by using both previousLocationInView: and locationInView:, and updating maskPreview.center instead of maskPreview.frame. You won't even need the originalOrigin instance variable:

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

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if ([touches count]==1) {
        UITouch *touch = [touches anyObject];
        CGPoint p0 = [touch previousLocationInView:maskPreview];
        CGPoint p1 = [touch locationInView:maskPreview];
        CGPoint center = maskPreview.center;
        center.x += p1.x - p0.x;
        center.y += p1.y - p0.y;
        maskPreview.center = center;
    }
}

Another way to do this is by using a UIPanGestureRecognizer. I leave that as an exercise for the reader.

like image 42
rob mayoff Avatar answered Oct 04 '22 03:10

rob mayoff