2

画面全体に配置されたデフォルトのUIviewがあるViewControllerがあります。このビューにいくつかのUIImageView(たとえば約20)を追加しました。これらのUIImageView間での画像の交換をサポートしたいと思います。私はすでにUITapGestureRecogniserを使用して、これらのUIImageViewで発生するタッチを処理しました。このUITapGestureRecogniserイベント自体の下でこれらのUIImageView間の画像のドラッグアンドドロップを処理できますか?(または)UIPanGestureRecognizerまたはタッチイベントを使用する必要がありますか?これらのUIImageView間で画像のドラッグアンドドロップを実現するための最も簡単で簡単な方法は何ですか?提案してください?

ありがとうございました!

4

3 に答える 3

3

いくつかの考え。

  1. これはタップ ジェスチャで実現できますが (たとえば、最初の画像ビューをタップし、目的の画像ビューをタップします)、あまり直感的ではありません。を使用して適切なドラッグ アンド ドロップを行うUIPanGestureRecognizerと、エンド ユーザーにとってはるかに直感的になります。

  2. 技術的には、画像ビューから画像をドラッグするのではなく、実際に画像ビュー自体をドラッグします。(画像自体は、画像ビューなしでは視覚的表現を持ちません。) そして手を離すと、画像ビュー フレームの変化をアニメートして錯覚を完成させます。


の NSArray がある場合imageViews、スーパービューにジェスチャーを追加できます。

@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];
}
于 2013-02-19T20:08:51.253 に答える
2

ロブの答えは素晴らしかった。handlePan画像のホットスワップを可能にするために、彼の方法を少し修正しました。

ホットスワップ

- (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;
                         }];
    }
}
于 2013-07-19T15:09:52.717 に答える
0

実際、タップ ジェスチャはまったく使用しないでください。

その秘密は、imageView のスーパービューを使用することです。

3 つの画像ビューが必要です....

UIImageView *ImageViewA

UIImageView *ImageViewB

UIImageView *DraggableImageView

画面をクリックすると、ホストビューが touchesBegan イベントを取得するとします... ImageViewA を取得して、次の方法で rect をテストすると、次のようになります。

[rect containsPoint:touchPoint];

これが true で、最初の imageView へのタッチに成功した場合は、次のように touchesMoved でドラッグ操作を開始します。

ImageViewA.superview を取得すると、ビューのホスト ビューが表示されます... ホスト ビューは次のコマンドを受け取ります。

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

UIResponder メソッド touchesBegain touchesMoved および touchesEnded を使用して、ホスト ビューでタッチ イベントを追跡するようになりました。

touchesMoved: 動きの座標を newDruggableImageView のフレームに送信します...

ドラッグしているように... touchesEndedメソッドの1つ:

画像のフレームが 2 番目のドラッグ スポットのフレーム内にある場合は、最終的な画像ビューを設定できます。

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

申し訳ありませんが、これは疑似コードです...論理フローを理解していただければ幸いです...ホストビューに画像を追加する...またはアプリケーションのウィンドウビューに画像を追加して移動します...移動が終了したら..位置をテストしますimageViewの新しい画像ビューを適切に設定します...

幸運を!そしてハッピーコーディング!

于 2013-02-19T21:53:10.307 に答える