2012-02-03 46 views
5

我正在尝试为我的imageView(下面的代码中的maskPreview)创建移动功能,以便用户可以在屏幕上移动一张包含在maskPreview中的图片。这里是我的代码触摸开始和触摸移动:如何用触摸移动UIImageView

-(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)]; 
} 
} 

但我从应用程序得到一些奇怪的反应。我没有限制imageview可以移动多远,也就是说,为了防止它离开屏幕,但即使这只是一个小动作,我的图像视图也会变得疯狂并消失。

非常感谢提前对所有帮助

回答

9

实施touchesBegan等是矫枉过正的方式在这个现代世界。你只是混淆了自己,而你的代码很快就变得不可能理解或维护。使用UIPanGestureRecognizer;这就是它的目的。使用UIPanGestureRecognizer制作视图是可以拖动的。以下是可使视图可拖动的UIPanGestureRecognizer的操作处理程序:

- (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]; 
    } 
} 
+0

太棒了马特,你是一个绝对的天才!会评价你的答案,但我没有足够的声望!让我的生活变得如此轻松! – Septronic 2012-02-03 13:47:23

+0

只是仅供参考,代码直接出我的书:http://shop.oreilly.com/product/0636920023562.do - 更多的地方来自... – matt 2012-02-03 14:31:21

+0

真棒,我会研究它:)谢谢 – Septronic 2012-02-03 14:47:50

2

您的代码有两个问题。首先,这条线是错误的:

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

它应该是这样的:

CGPoint lastTouch = [touch previousLocationInView:maskPreview]; 

真的,你甚至不应该使用previousLocationInView:。你应该只使用locationInView:这样的:

CGPoint lastTouch = [touch locationInView:maskPreview]; 

其次,你得到的movedDistanceXmovedDistanceY错误的迹象。他们改成这样:

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

而且,touchesBegan:withEvent:文档这样说:

如果重写此方法无需调用super(一种常见的使用模式),您还必须重写为其他方法处理触摸事件,如果仅作为存根(empy)实现。

因此,请确保你也覆盖touchesEnded:withEvent:touchesCancelled:withEvent:

无论如何,你可以做得更简单一点。一种方法是使touchesBegan:withEvent:为空,并通过使用previousLocationInView:locationInView:以及更新maskPreview.center而不是maskPreview.frame来完成touchesMoved:withEvent:中的所有工作。你甚至不会需要originalOrigin实例变量:

-(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; 
    } 
} 

另一种方式做,这是通过使用UIPanGestureRecognizer。我把它作为读者的练习。

+0

嗨,罗布,感谢您的答案,并意识到我的代码中的错误!我使用了UIPanGestureRecognizer的Matt的教程,它工作得很好。但是关于重复所有触摸事件的一点帮助很大,我不知道,也不认为我们应该这样做。 – Septronic 2012-02-03 13:51:44