【Swift】Pinch Gesture Recognizerの使い方。2つの指で部品を拡大縮小する。(Swift 2.1、XCode 7.2)
Pinch Gesture Recognizerとは
本記事ではSwiftで使える部品のPinch Gesture Recognizer(以下、ピンチリコグナイザー)について説明する。
ピンチリコグナイザーとは、部品を2つの指で摘んで外側に広げたとき、または、内側に狭めたときを検知する部品である。ちなみに、外側に広げる動作をピンチアウト、内側に狭める動作をピンチインという。
ピンチイン、ピンチアウトを使う場面といえば、地図の目的地付近をもっと細かく見たいときや、画面の文字や画像が小さくてよく見えないときなどに使われる。
ピンチリコグナイザーを使ってみる
実際にピンチリコグナイザーを使ってみよう。デバイス画面にラベルを配置してピンチイン、ピンチアウトで拡大縮小させる動きを実装する。
デバイス画面にラベルを配置する(下図赤矢印)。紫枠のアシスタントエディタボタンを押してViewController.swfitを開く。Ctrlキーを押しながらラベルをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる。
Connectionに「Outlet」、Nameの「testLabel」を入力しConnectボタンを押す。これでラベルをソースコードから操作できるようになった。
続いて、黄枠のアトリビュートインスペクタボタンを押して設定画面を表示する。Textに「テスト」、Colorを白、Backgroundに青、User Interaction Enabledにチェックを入れる。
ピンチリコグナイザーをラベルに配置する(下図赤矢印)。Ctrlキーを押しながら黄緑枠のピンチリコグナイザーをソースコードまで運んで吹き出しの設定画面を表示させる(青矢印)。
Connectionに「Action」、Nameに「pinchLabel」、Typeに「UIPinchGestureRecognizer」を設定し、Connectボタンを押す。これでラベルがピンチされたときのイベントソースコードで受けれるようになった。
ViewController.swiftを以下のコードに変更する。
UIViewを継承したすべての部品はtransformプロパティを持っていて、この値にアフィン変換を設定することで部品の拡大縮小、回転を行う。アフィン変換とは物体の形状を維持したまま拡大縮小、回転を行う変換のことである。
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 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testLabel: UILabel! //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() } //ピンチ時の呼び出しメソッド @IBAction func pinchLabel(sender: UIPinchGestureRecognizer) { //アフィン変換でラベルを拡大縮小する。 testLabel.transform = CGAffineTransformMakeScale(sender.scale, sender.scale) } } |
以下は実際のプレイ動画
「ピンチ時の呼び出しメソッド」はピンチしている指が移動する度に呼び出される。ピンチが検知された瞬間の指と指の距離が基準値1.0となり、基準値に対する現在の拡大率が引数に含まれている。
ピンチの拡大率が2.0になったらアフィン変換によって部品の縦横も2倍する。逆に、ピンチの拡大率が0.5になったら部品の縦横も2分の1にするという流れである。
ちなみに、2つの指が画面に触れたときの距離が広くても狭くても基準値は同じ1.0になるので、距離が広い状態から拡大率を2.0にするのと、狭い状態から2.0にするのに必要な移動距離が異なる。なので、素早く部品を拡大したいときは指を狭めた状態からピンチを開始するのが良い。
前回ピンチの拡大率を引き継ぐ
先ほどのコードには1つ欠点がある。それは、部品を拡大縮小したあとに再びピンチをおこなうと、元のサイズから拡大縮小が行われる点である。なぜなら、CGAffineTransformMakeScaleによって作られるアフィン変換は元のサイズを基準としたものだからだ。
これではサイズを微調整したいときにやり辛いので、コードを以下のように変更する。
ピンチ開始時のアフィン変換をクラス変数に保持し、CGAffineTransformScaleを使ってピンチ開始時のアフィン変換を引き継いだアフィン変換を作っている。これで、サイズが元に戻ることなくピンチを再開することができる。
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 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testLabel: UILabel! var startTransform:CGAffineTransform! //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() } //ピンチ時の呼び出しメソッド @IBAction func pinchLabel(sender: UIPinchGestureRecognizer) { if(sender.state == UIGestureRecognizerState.Began){ //ピンチ開始時のアフィン変換をクラス変数に保持する。 startTransform = testLabel.transform } //ピンチ開始時のアフィン変換を引き継いでアフィン変換を行う。 testLabel.transform = CGAffineTransformScale(startTransform, sender.scale, sender.scale) } } |
以下は実際のプレイ動画
ピンチリコグナイザーを配置した部品の内部にある部品も一緒に拡大縮小してくれるのが嬉しい。