【Swift】Pan Gesture Recognizerの使い方。ドラッグ&ドロップを検知する。(Swift 2.1、XCode 7.2)

2020年6月16日

Pan Gesture Recognizerとは

本記事ではSwiftで使える部品のPan Gesture Recognizer(以下、パンリコグナイザー)について説明する。

Pan Gesture Recognizer

 

パンリコグナイザーとは、ドラッグ&ドロップを検知する部品である。前回記事のスワイプリコグナイザーは素早く指を動かさなければ検知されないが、パンリコグナイザーはゆっくり指を動かしても検知され、元の位置からの移動量を正確に把握することができる。⇒「スワイプリコグナイザーの記事

 

部品をドラッグ&ドロップする。

ドラッグ&ドロップでイメージするものといえば部品をつかんで運ぶ動作だ。パンリコグナイザーを使って実装してみよう。

デバイス画面にラベルを配置する(下図赤矢印)。紫枠のアトリビュートインスペクタボタンを押して設定画面を表示する。Textに「テスト」、Colorに白、Backgroundに緑、User Interaction Enabledにチェックを入れる。

黄緑枠のアシスタントエディタボタンを押してViewController.swiftを開く。Ctrlキーを押しながらラベルをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示する。Connectionに「Outlet」、Nameに「testLabel」を入力してConnectボタンを押す。これで、ソースコードでラベルを操作できるようになった。

ラベルをデバイス画面に配置する

 

パンリコグナイザーをラベルに配置する(下図赤矢印)。Ctrlキーを押しながら水色枠のパンリコグナイザーをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる。

Connectionに「Action」、Nameに「panLabel」、Typeに「UIPanGestureRecognizer」を設定してConnectボタンを押す。これでラベルをドラッグ&ドロップしたときのイベントをソースコードで受けれるようになった。

Pan Gesture Recognizerをラベルに配置する

 

ViewController.swiftを以下のコードに変更する。

「ドラッグ時の呼び出しメソッド」が指を移動するたびに呼び出されるので、引数から移動量を取得してラベルの座標に加算している。移動量は蓄積する値なので0にしてからメソッドを抜けることで次の呼び出しに備えている。

 

以下は実際のプレイ動画

ラベルを更新すると元の位置に戻ってしまう

上記コードでは1つ不思議な事象が発生する。ラベルに移動量を表示する処理(コメントアウト箇所)を入れると、以下の動画のようにラベルが元の位置にすぐに戻ってしまうのだ。

 

解消方法は、AutoLayoutを使って部品に位置の制約を追加し、制約の更新で部品を移動する作りにすることである。実際にやってみよう。

下図赤枠のAlignボタンを押して吹き出しの設定画面を表示させる。Horizontally in Container と Vertically in Containerにチェックを入れ、両方とも「0」を入力して「Add 2 Constraints」ボタンを押す。これで、どんな画面サイズでも、アプリ起動時のラベルは必ず画面中央に配置されるようになった。

ラベルに位置の制約を追加する

 

下図紫枠のPinボタンを押して吹き出しの設定画面を表示させる。HeightとWidthにチェックを入れて、「Add 2 Constraints」ボタンを押す。これでラベルのサイズが固定された。

ラベルにサイズの制約を追加する

 

下図紫枠のアシスタントエディタボタンを押してVeiwController.swiftを表示する。

Ctrlキーを押しながら赤枠のパンリコグナイザー(Test Label.centerX = centerX)をドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる。Connectionに「Outlet」、Nameに「xConstraint」を入力し、Connectボタンを押す。

黄緑枠のパンリコグナイザー(Test Label.centerY = centerY)も同じようにして吹き出しの設定画面を表示し、Connectionに「Outlet」、Nameに「yConstraint」を入力し、Connectボタンを押す。これでラベルの位置の制約をソースコードで操作できるようになった。

ラベルの制約とソースコードのコネクションを確立する

 

ViewController.swiftを以下のコードに修正する。

 

以下は実際のプレイ動画。ラベルの表示を更新しても元の位置に戻らなくなった。