2013-02-19 60 views
1

我有一個視圖控制器,其中有一個默認的UIview放置整個屏幕。在這個視圖中,我添加了幾個UIImageView(比如20左右)。我想支持在這些UIImageView之間交換圖像。我已經使用UITapGestureRecogniser來處理在這些UIImageView上發生的觸摸事件。我可以在這個UITapGestureRecogniser事件本身下處理這些UIImageView之間的圖像拖放嗎? (或)我是否需要使用UIPanGestureRecognizer或觸摸事件?在這些UIImageView之間實現拖放圖像的最簡單和最簡單的方法是什麼?請建議?iOS:在UIImageView之間移動圖像

謝謝!

回答

3

一些想法。

  1. 你可以做到這一點用自來水手勢(例如先點擊圖片查看,點擊目標圖像視圖),但它不是很直觀。對UIPanGestureRecognizer進行適當的拖放操作對於最終用戶來說會更加直觀。

  2. 從技術上說,你不是從圖像視圖拖動圖像,而是實際上是拖動圖像視圖本身。 (一個圖像本身沒有圖像視圖,沒有可視化表示。)當你放開時,你將動畫改變圖像視圖幀來完成幻覺。


如果你有的imageViews一個NSArray的,你可以手勢添加到他們的上海華:

@property (nonatomic, strong) NSMutableArray *imageViews; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [self createImageViewArray]; 

    UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self 
                       action:@selector(handlePan:)]; 
    [self.view addGestureRecognizer:gesture]; 
} 

- (void)createImageViewArray 
{ 
    self.imageViews = [NSMutableArray array]; 

    // add your imageviews to the array any way you want 

    ... 
} 

- (void)handlePan:(UIPanGestureRecognizer *)gesture 
{ 
    static UIImageView *draggedImage = nil; 
    static CGRect draggedImageOriginalFrame; 

    CGPoint location = [gesture locationInView:gesture.view]; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     // see if we grabbed an imageview 

     draggedImage = [self determineImageForLocation:location]; 

     // if so, save its old location for future reference and bring it to the front 

     if (draggedImage) 
     { 
      draggedImageOriginalFrame = draggedImage.frame; 
      [draggedImage.superview bringSubviewToFront:draggedImage]; 
     } 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged && draggedImage != nil) 
    { 
     // if we're dragging it, then update its location 

     CGPoint translation = [gesture translationInView:gesture.view]; 
     CGRect frame = draggedImageOriginalFrame; 
     frame.origin.x += translation.x; 
     frame.origin.y += translation.y; 
     draggedImage.frame = frame; 
    } 
    else if (draggedImage != nil && (gesture.state == UIGestureRecognizerStateEnded || 
            gesture.state == UIGestureRecognizerStateCancelled || 
            gesture.state == UIGestureRecognizerStateFailed)) 
    { 
     // if we let go, let's see if we dropped it over another image view 

     UIImageView *droppedOver = nil; 

     if (gesture.state == UIGestureRecognizerStateEnded) 
      droppedOver = [self draggedImageView:draggedImage toLocation:location]; 

     if (droppedOver == nil) 
     { 
      // fail; animate the restoring of the view back to it's original position 

      [UIView animateWithDuration:0.25 
          animations:^{ 
           draggedImage.frame = draggedImageOriginalFrame; 
          }]; 
     } 
     else 
     { 
      // succeed; make sure to bring the view we're about to animate to the front 

      [droppedOver.superview bringSubviewToFront:droppedOver]; 

      // animate the swapping of the views 

      [UIView animateWithDuration:0.25 
          animations:^{ 
           draggedImage.frame = droppedOver.frame; 
           droppedOver.frame = draggedImageOriginalFrame; 
          }]; 
     } 
    } 
} 

// see if we dragged an imageview over one of our imageviews, returning a point 
// to the image view we dropped it over 

- (UIImageView *)draggedImageView:(UIImageView *)draggedView toLocation:(CGPoint)location 
{ 
    for (UIImageView *imageview in self.imageViews) 
     if (CGRectContainsPoint(imageview.frame, location) && imageview != draggedView) 
      return imageview; 

    return nil; 
} 

// see if we started the gesture over an imageview 
// (turns out that this is the same as "did we drag an image over another", 
// but as we're not dragging an image yet, just pass nil) 

- (UIImageView *)determineImageForLocation:(CGPoint)location 
{ 
    return [self draggedImageView:nil toLocation:location]; 
} 
+0

好,知道了!謝謝。我還有一個疑問是,在這種情況下,如何將兩個圖像視圖移動(交換)到指定的交換位置。 – Getsy 2013-02-19 20:25:29

+0

@Getsy查看示例代碼。請注意,如果您在「NSArray」中獲得圖像視圖,則這類內容總是會簡化,因此您可以通過它們快速枚舉。 – Rob 2013-02-19 21:19:46

0

不要使用自來水的手勢在所有的事實。

祕訣就是使用imageView的superview。

您需要3圖像視圖的....

UIImageView *ImageViewA 

UIImageView *ImageViewB 

UIImageView *DraggableImageView 

假設你點擊屏幕和主機觀點得到了的touchesBegan事件......如果你把ImageViewA並測試它的矩形與下面的方法:

[rect containsPoint:touchPoint]; 

如果這是真的,你已經成功地觸動了第一ImageView的...開始在touchesMoved的拖動操作像如下:

如果你拿ImageViewA.superview你會得到視圖的主視圖...主視圖應該再收到以下命令:

[newDraggableImageView setFrame:ImageViewA.frame]; 
[newDraggableImageView setImage:ImageViewA.image]; 
[hostView addSubview:newDraggableImageView]; 

現在你跟蹤與UIResponder方法touchesBegain touchesMoved主視圖觸摸事件和touchesEnded

當你經歷touchesMoved:將運動的座標發送到newDraggableImageView的框架中...

因爲它正在拖動...一項所述的方法touchesEnded:

如果圖像的幀爲第二拖動點的框內然後可以設置最終圖像視圖

if ([frame containsRect:anotherFrame]) 
    ImageViewB.image = draggableImageView.image; 

對不起這是僞代碼...希望你瞭解邏輯流程...將圖像添加到主機視圖...或應用程序的窗口視圖並移動它...一旦移動結束..測試imageView的位置並適當設置新的圖像視圖。 ..

GOODLUCK!和快樂編碼!

1

Rob的回答非常好。我稍微修改了他的handlePan方法以允許熱插拔圖像。

hot swapping

- (void)handlePan:(UIPanGestureRecognizer *)gesture 
{ 
    static UIImageView *draggedImage = nil; 
    static CGRect draggedImageLastFrame; 

    CGPoint location = [gesture locationInView:gesture.view]; 

    if (gesture.state == UIGestureRecognizerStateBegan) { 

     // see if we grabbed an imageview 

     draggedImage = [self determineImageForLocation:location]; 

     // if so, save its old location for future reference and bring it to the front 

     if (draggedImage) { 
      draggedImageLastFrame = draggedImage.frame; 
      [draggedImage.superview bringSubviewToFront:draggedImage]; 
      draggedImage.alpha = 0.6f; 
     } 

    } else if (gesture.state == UIGestureRecognizerStateChanged && draggedImage != nil) { 

     // if we're dragging it, then update its horizontal location 

     CGPoint translation = [gesture translationInView:gesture.view]; 
     CGRect frame = draggedImage.frame; 
     frame.origin.x += translation.x; 
     draggedImage.frame = frame; 
     [gesture setTranslation:CGPointZero inView:gesture.view]; 

     UIImageView *draggedOver = [self draggedImageView:draggedImage toLocation:location]; 
     if (draggedOver != nil) { 

      // animate the draggedOver image to the the draggedImage's last location 

      [UIView animateWithDuration:0.25 
          animations:^{ 
           CGRect currentFrame = draggedOver.frame; 
           draggedOver.frame = draggedImageLastFrame; 
           draggedImageLastFrame = currentFrame; 
          }]; 
     } 

    } else if (draggedImage != nil && (gesture.state == UIGestureRecognizerStateEnded || 
             gesture.state == UIGestureRecognizerStateCancelled || 
             gesture.state == UIGestureRecognizerStateFailed)) { 

     // finished, animate the draggedImage into place 

     [UIView animateWithDuration:0.25 
         animations:^{ 
          draggedImage.frame = draggedImageLastFrame; 
          draggedImage.alpha = 1.0f; 
         }]; 
    } 
}