【Swift】Screen Edge Pan Gesture Recognizerの使い方。画面端のドラッグを検知する。(Swift 2.1、XCode 7.2)
Screen Edge Pan Gesture Recognizerとは
本記事ではSwiftで使える部品のScreen Edge Pan Gesture Recognizer(以下、スクリーンエッジリコグナイザー)について説明する。
スクリーンエッジリコグナイザーとは、画面端のドラッグを検知する部品である。iOSの画面端から内側に向かってスワイプしたときにニョキッと現れる通知センターやコントロールセンターもスクリーンエッジリコグナイザーが使われている。
スクリーンエッジリコグナイザーを使ってみる
では、スクリーンエッジリコグナイザーを使って通知センターの登場シーンのようなものを作ってみよう。以降の手順は、「Blur Effectの使い方」の続きになるので、実装を試してみる人は先に読んでおくことをお勧めする。
スクリーンエッジリコグナイザーを部品一覧の「View」まで運ぶ(下図赤矢印)。すると紫枠のスクリーンエッジリコグナイザーが追加される。
水色枠のアトリビュートインスペクタボタンを押して設定画面を表示し、EdgesのTopにチェックを入れる。
黄緑枠のアシスタントエディタボタンを押してViewController.swiftを開く。Ctrlキーを押しながら紫枠のスクリーンエッジリコグナイザーをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる。
Connectionに「Action」、Nameに「panTop」、Typeに「UIScreenEdgePanGestureRecognizer」を設定してConnectボタンを押す。これで、画面上端をドラッグしたイベントをソースコードで受けれるようになった。
下図黄枠の「Tap Gesture Recognizer」はDeleteボタンを押して消す。
ViewController.swiftを以下のコードに変更する。
「画面上端ドラッグ時の呼び出しメソッド」で、垂直方向の移動量を位置の制約に加算して、ビューを画面内に移動している。
ドラッグ終了時に、下降中のビューが画面高さの半分以上まできた場合はそのままビューを下げ、半分に満たない場合はビューを画面外に戻している。
普通に実行して画面上端をドラッグするとiOS標準の通知センターが降りてきてしまうので、「ステータスバーの表示要否メソッド」をオーバーライドしてステータスバーがすぐに降りないようにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testLabel: UILabel! @IBOutlet weak var topConstraint: NSLayoutConstraint! //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() let testDate = NSDate() let testFormatter = NSDateFormatter() //ロケールを設定する。 testFormatter.locale = NSLocale(localeIdentifier:"ja_JP") //フォーマットのスタイルを設定する。 testFormatter.dateStyle = .MediumStyle //ラベルに日付を設定する。 testLabel.text = testFormatter.stringFromDate(testDate) } //画面上端ドラッグ時の呼び出しメソッド @IBAction func panTop(sender: UIScreenEdgePanGestureRecognizer) { //移動量を取得する。 let move:CGPoint = sender.translationInView(view) //位置の制約に垂直方向の移動量を加算する。 topConstraint.constant += move.y //画面表示を更新する。 self.view.layoutIfNeeded() //ドラッグ終了時の処理 if(sender.state == UIGestureRecognizerState.Ended) { if(topConstraint.constant < -view.frame.size.height/2) { //ドラッグの距離が画面高さの半分に満たない場合はビュー画面外に戻す。 topConstraint.constant = -view.frame.size.height } else { //ドラッグの距離が画面高さの半分以上の場合はそのままビューを下げる。 topConstraint.constant = 0 } //アニメーションさせる。 UIView.animateWithDuration(0.8,animations: { self.view.layoutIfNeeded()},completion:nil) } //移動量をリセットする。 sender.setTranslation(CGPointZero, inView: view) } //ステータスバーの表示要否メソッド override func prefersStatusBarHidden() -> Bool { return true } } |
以下は実際のプレイ動画
スクリーンエッジリコグナイザーを使う上での注意点
スクリーンエッジリコグナイザーを使う上でいくつか気になった点があるので以下に記載しておく。Swift 2.1、XCode 7.2で確認された事象。
気になった点1
スクリーンエッジリコグナイザーの設定項目にEdgesがあるが、2つ以上選択すると検知メソッドが呼び出されなくなった。2つ以上の設定が必要な場合はスクリーンエッジリコグナイザーを複数登録し、1個のリコグナイザーにつき1個のEdgesを設定すると正常に検知できるようになった。
気になった点2
過去のバージョンで、ストーリーボードからスクリーンエッジリコグナイザーを配置すると検知メソッドが呼び出されなくなる事象が発生していた。ソースコードから登録すると正常に検知される。⇒「stackoverflowの投稿」
気になった点3
画面サイズより小さい部品にスクリーンエッジリコグナイザーを登録しても検知させることができる。以下の動画はEdgesにLeftを設定して、検知させたプレイ動画。
部品の左端をドラッグすると検知される。
ただし、部品の端が検知されるわけではなく、画面の端を含めた部品の領域しか検知されない。例えば、画面端から部品が離れた状態にあると、以下の動画のように画面や部品の端をドラッグしても検知されない。
といっても、画面端と部品端がピッタリくっついていなければならないということでは無く、以下の動画のように、画面端と部品端に少し隙間があっても検知される。
検知可能になる具体的なピクセル数については分かり次第追記する。