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
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];
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With