2013-02-19 82 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; 
         }]; 
    } 
}