web-dev-qa-db-ja.com

iOSの基本的なドラッグアンドドロップ

私は、ユーザーがドラッグアンドドロップすることのできる車が走っているビューを望んでいます。これを行うための最良の大規模戦略は何だと思いますか?車両を表すビューからタッチイベントを取得するのが最善ですか、それともより大きなビューからですか?あなたが満足しているドラッグアンドドロップに使用したシンプルなパラダイムはありますか?さまざまな戦略の欠点は何ですか?

93
Luke

背景画像と多くのUIViewを含むvehiclesシーンがあると仮定すると、それぞれの新しいビークルをUIButtonとして定義できます(UIImageViewもおそらく機能します)。

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];

次に、UIControlEventTouchDragInsideイベントに応答することにより、車両を好きな場所に移動できます。例:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    CGPoint point = [[[event allTouches] anyObject] locationInView:self.view];
    UIControl *control = sender;
    control.center = point;
}

シーン全体を管理する場合と比較して、個々の車両が独自のドラッグを処理する方がはるかに簡単です。

126
ohho

Ohhoの答えに加えて、同様の実装を試みましたが、「高速」ドラッグとドラッグ中心への問題はありませんでした。

ボタンの初期化は...

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragOutside];
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];

およびメソッドの実装:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    UIControl *control = sender;

    UITouch *t = [[event allTouches] anyObject];
    CGPoint pPrev = [t previousLocationInView:control];
    CGPoint p = [t locationInView:control];

    CGPoint center = control.center;
    center.x += p.x - pPrev.x;
    center.y += p.y - pPrev.y;
    control.center = center;
}

これが答えの完璧なソリューションだとは言いません。それにもかかわらず、私はこれがドラッグするための最も簡単な解決策であることがわかりました。

34
JakubKnejzlik

他の複数のuiview間でuiviewをドラッグ/ドロップしたい場合がありました。その場合、すべてのドロップゾーンとすべてのドラッグゲーブルオブジェクトを含むスーパービューでパンイベントをトレースする最適なソリューションを見つけました。実際のドラッグされたビューにイベントリスナーを追加しない主な理由は、ドラッグされたビューのスーパービューを変更するとすぐに進行中のパンイベントが失われたことです。

代わりに、単一または複数のドロップゾーンで使用できるかなり汎用的なドラッグドロップソリューションを実装しました。

ここに見ることができる簡単な例を作成しました: 他の複数のuiviewsの間にドロップuiviewsをドラッグ

他の方法を選択する場合は、uibuttonの代わりにuicontrolを使用してみてください。 addTargetメソッドを宣言し、拡張がはるかに簡単です。したがって、カスタムの状態と動作を提供します。

2
jeyben

特別な理由がない限り、実際には大きなビューではなく、車両ビュー自体でドラッグを追跡します。

ユーザーがアイテムを画面上にドラッグして配置できるようにするケースがあります。その場合、top viewchild viewの両方をドラッグ可能にして実験しました。 UIViewにいくつかの「ドラッグ可能な」ビューを追加し、それらをドラッグする方法を処理すると、コードがすっきりすることがわかりました。親UIViewへの簡単なコールバックを使用して、新しい場所が適切かどうかを確認しました。そのため、アニメーションで示すことができました。

トップビュートラックのドラッグは良いと思いますが、ボタンなど、ユーザーと対話するドラッグできないビューを追加する場合は、少し面倒になります。

1
Magnus
-(void)funcAddGesture
{ 

 // DRAG BUTTON
        UIPanGestureRecognizer *panGestureRecognizer;
        panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragButton:)];
        panGestureRecognizer.cancelsTouchesInView = YES;

        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(50, 100, 60, 60);
        [button addTarget:self action:@selector(buttontapEvent) forControlEvents:UIControlEventPrimaryActionTriggered];
        [button setImage:[UIImage imageNamed:@"button_normal.png"] forState:UIControlStateNormal];
        [button addGestureRecognizer:panGestureRecognizer];
        [self.view addSubview:button];
}


- (void)dragButton:(UIPanGestureRecognizer *)recognizer {

    UIButton *button = (UIButton *)recognizer.view;
    CGPoint translation = [recognizer translationInView:button];

    float xPosition = button.center.x;
    float yPosition = button.center.y;
    float buttonCenter = button.frame.size.height/2;

    if (xPosition < buttonCenter)
        xPosition = buttonCenter;
    else if (xPosition > self.view.frame.size.width - buttonCenter)
        xPosition = self.view.frame.size.width - buttonCenter;

    if (yPosition < buttonCenter)
        yPosition = buttonCenter;
    else if (yPosition > self.view.frame.size.height - buttonCenter)
        yPosition = self.view.frame.size.height - buttonCenter;

    button.center = CGPointMake(xPosition + translation.x, yPosition + translation.y);
    [recognizer setTranslation:CGPointZero inView:button];
}


- (void)buttontapEvent {

    NSLog(@"buttontapEvent");
}
1
Balaji G

ohhoの答えは私にとってはうまくいきました。 Swift 2.xバージョンが必要な場合:

override func viewDidLoad() {

    let myButton = UIButton(type: .Custom)
    myButton.setImage(UIImage(named: "vehicle"), forState: .Normal)

    // drag support
    myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragInside)
    myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragOutside)
}

private func imageMoved(sender: AnyObject, event: UIEvent) {
    guard let control = sender as? UIControl else { return }
    guard let touches = event.allTouches() else { return }
    guard let touch = touches.first else { return }

    let prev = touch.previousLocationInView(control)
    let p = touch.locationInView(control)
    var center = control.center
    center.x += p.x - prev.x
    center.y += p.y - prev.y
    control.center = center
}
1
parag

For Swift 4簡単で簡単な方法。????

ステップ1:ストーリーボードからView Controllerにボタンを接続します。そして、すべての基本的な自動レイアウト制約を設定します

 @IBOutlet weak var cameraButton: UIButton!

ステップ2:ボタンにパンジェスチャーを追加InviewDidLoad()

self.cameraButton.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(panGesture:))))

ステップ3:

PanGestureHandlerを追加

@objc func panGestureHandler(panGesture recognizer: UIPanGestureRecognizer) {

         let location = recognizer.location(in: view)
        cameraButton.center = location

    }

そしてあなたのボタンアクション

@IBAction func ButtonAction(_ sender: Any) {

        print("This is button Action")
    }

enter image description here

追加結果を見る☝️

0
Anup Gupta

IOS 11以降のドラッグアンドドロップを行う最良の方法は次のとおりです。

https://developer.Apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_custom_view

0
StevenOjo