LoginSignup
6
8

More than 5 years have passed since last update.

[iOS] ビューをドラッグして動かす

Last updated at Posted at 2019-03-26

以下のように、ボタンをタップしてビューを追加し、それをドラッグして動かせるようにします。

drag.gif

実装方法

以下のように役割を分けて実装します。

  • ViewController: ビューを追加するボタンを提供する
  • MainView: ビューをドラッグして移動させる処理を行う

ViewController

ViewControllerでは、ツールバーの設置とボタンタップ時にビューを追加する処理を実装します。
StoryBoardにて、このViewControllerのルートビューの型をMainViewに設定しています。

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    private func setup() {
        navigationController?.isNavigationBarHidden = true
        navigationController?.isToolbarHidden = false

        let addButton = UIBarButtonItem(
            barButtonSystemItem: .add,
            target: self,
            action: #selector(addView))
        toolbarItems = [
            .init(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            addButton,
            .init(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)]
    }

    @objc func addView() {
        let v = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        v.backgroundColor = .black
        let mainView = view as! MainView
        mainView.addSubview(v)
    }
}

MainView

ビューをドラッグして移動させる処理はこちらのクラスで実装しています。

import UIKit

class MainView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    private func setup() {
        backgroundColor = .lightGray
    }

    override func addSubview(_ view: UIView) {
        super.addSubview(view)
        view.center = center
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        // [1]
        guard let touch = touches.first, let view = touch.view else { return }

        // [2]
        if view != self {
            view.center = touch.location(in: self)
        }
    }
}

メインとなる実装はtouchesMoved(_:with:)メソッドです。
このメソッドはMainView上にあるビューをタッチしたまま動かしたときに呼ばれます。

[1]
タッチ操作に関する情報を保持するUITouchクラスのインスタンスを取得します。
デフォルトではインスタンスは1つだけ格納されています。
isMultipleTouchEnabledtrueにすると複数タッチに対応し、インスタンスが複数格納されます。

さらに、タッチが検出されたビューをviewプロパティから取得しています。

[2]
タッチが検出されたビューが自分自身でないことを確認します。
ドラッグして動かしたいのはサブビューであるためです。

locationプロパティから現在のドラッグ位置を取得することができます。
ビューの位置をこのドラッグ位置に合わせることで、指のドラッグに合わせてビューを動かすことができます。

まとめ

ドラッグしてビューを動かす実装について紹介しました。
今回はtouchesMoved(_:with:)だけを実装しましたが、本来であれば同じタッチ関連のメソッドであるtouchesBegan(_:with:)等の実装も合わせて行う必要があります。
これはレスポンダーチェインに関連した話ですが、今回の記事の範囲からは離れるのでここでは取り上げません。
詳細は公式ドキュメントをご確認ください。

リファレンス

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8