2012-02-03 45 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