Swiftで遊ぼう! - 420 - UIKit Dynamics and Swift Tutorial: Tossing Views 1
Swiftで遊ぼう!の古い記事-> Life-LOG OtherSide
前回までにDynamicAnimatorの基本的なチュートリアルを終えました。しかし、インタラクティブな動きを制御する「UISnapBehavior」の理解は不十分に終わっています。新しい課題を「RAYWENDERLICHのチュートリアスサイト」からピックアップして、もう少し物理空間とインタラクティブな動きの勉強をします。
基本的にはUIDynamicsのチュートリアルになる。今回はUIKitフレームワークを使って、イメージを指ではねて飛ばしてしまいましょう。言葉で説明するより上記のリンクにあるイメージをみるといいです。
Xcode7.0(β)になって、Autolayoutの取り扱いに変更が加わっているので勉強をしなければならないんですが、今回のチュートリアルはAutolayoutを使わないので、今のところ自分に好都合で早速プロジェクトを作ります。
新しいプロジェクトは「DynamicToss」にします。「Single View Application」を選択して保存します。
Autolayoutを無視するためにプロジェクトの「Genaral」タブの「Device Orientation」の「Portrait」だけ残して後はすべてアンマークします。
次に「Main.storyboard」を選択して、右のインスペクタペインのファイル・インスペクタを選び、中断にある「Use Auto Layout」と「Use Size Classes」のチェックを外します。
これでストーリーボードの形がiPhoneと同じになります。
次にデフォルトviewにImage ViewオブジェクトとViewオブジェクトを設置します。
ライブラリペインのオブジェクトライブラリから「Image View」をドラッグ&ドロップして、サイズインスペクタでサイズを位置を変更します(X=33, Y=137, Width=254, Height=172)。白い四角いスペースができます。
指定されたイメージをダウンロードしてアンZipしてjpegファイルを用意します。プロジェクトで扱うイメージはAssets xcassetsなので、「+」ボタンを押して、「New Image Set」を選択します。名前を「Images」に改名して、2×のスポットにイメージをドラッグ&ドロップします。
このままでストーリーボード上のImage Viewにダウンロードしたイメージは表示されません。ストーリーボード上のImage Viewを選択した状態で「アトリビュート・インスペクタ」を選択します。「Image View」の「Image」からAssets xcassetsで作ったImage Setの「Images」を選ぶと、ダウンどー℃したイメージが表示されます。
次に、サイズ・インスペクタを選択して、Autoresizingから「Top」と「Left」だけ選択して、後はオフにします。
次に2つのViewをストリーボードに設置します*1。
- View 1: (X=156, Y=219, Width=8, Height=8, バックグラウンドカラー:赤)
- View 2: (X=80, Y=420, Width=8, Height=8. バックグラウンドカラー:青)
これら3つのジェネリックなオブジェクトとコードを繋げていきます。チュートリアルでは、「@IBOutlet」の枕詞を付けてコードを書いてから、ジェネリックなオブジェクトに関連づけをしていますが、ジェネリックなオブジェクトを「Ctrl + ドラッグ」してコードと繋げるやり方が一般的です。
今までに何度も説明しているように、iOSフレームワークの利用に数々のバリエーションが存在することは理解しておかなければなりません。チュートリアルでは、Main.storyboardの上段にある「View Controller」を「Ctrl + クリック」して出てくるメニューウインドウの黒丸のプロパティを画面上のジェネリックなオブジェクトに関連付けてますが、下のイメージは既に関連づけられているので白丸に変わっています。
@IBOutlet weak var imageView: UIImageView! @IBOutlet weak var redSquare: UIView! @IBOutlet weak var blueSquare: UIView!
青い四角形は、タッチが始まったポイントを指して、赤い四角形は指の動きを追尾して動かせます。
これで役者は揃いました。ここから物理空間でインタラクティブな動きを加えていきます。前回のチュートリアルと同様にDnyamicAnimatorという空間を作って、その中でViewをDynamicItemとして扱います。
private var originalBounds = CGRect.zeroRect private var originalCenter = CGPoint.zeroPoint private var animator: UIDynamicAnimator! private var attachmentBehavior: UIAttachmentBehavior! private var pushBehavior: UIPushBehavior! private var itemBehavior: UIDynamicItemBehavior!
ここで何気なく読み飛ばしてしまいそうになりましたが、CGRect.zeroRectやCGPoint.zeroPointはグローバル・プロパティなんでしょうか?
originalBoundsに0サイズの四角形を作り、originalCenterに0ポイントを入れてつくられたということですね。それ以下のプロパティは物理空間を作り出すもので、「!」が付いているようにインスタンスのイニシャライズ・ステップで実装されなければなりません。オプショナル型にすることでクラス・イニシャライザ内にコードを書く必要は無くなります。
次にジェスチャーを認識するメソッドを実装します。また覚えなければならないメソッドが出てきました。
@IBAction func handleAttachmentGesture(sender: UIPanGestureRecognizer) { }
これを実装して「パン」というジェスチャーを見えるようにします。このメソッドは@IBActionが付いているのでstoryboardにジェネリックなPanGestureRecognaizerを作らないといけません。
@IBAction func handleAtttachmentGesture(sender: UIPanGestureRecognizer) { let location = sender.locationInView(self.view) let boxLocation = sender.locationInView(self.imageView) switch sender.state { case .Began: print("\(location)からタッチが始まります。") print("\(boxLocation)はイメージを中心とした開始点です。") case .Ended: print("\(location)でタッチは終了です。") print("\(boxLocation)はイメージを中心とした終点です。") default: break } }
画面上でクリックしてドラッグして指を離すとコンソールに位置が表示されるという仕組みです。
まだ、このメソッドは実装されていないのですが、今日はここまで。
*1:お決まりのオブジェクト・ライブラリからドラッグ&ドロップします。