【Swift】Colloction View Controllerの使い方。格子状に並んだセルをタップして画面遷移する。(Swift 2.1、XCode 7.2)
Collection View Controllerとは
本記事ではSwiftで使える部品のCollection View Controller(以下、コレクションビューコントローラー)について説明する。
コレクションビューコントローラーとは、UICollectionView(以下、コレクションビュー)を管理するコントローラーである。
部品の配置はTable View Controllerに似ていて、ビューコントローラーは直下にViewが配置されているのに対し、コレクションビューコントローラーは直下にCollection View(以下、コレクションビュー)が配置されているのが特徴である。
そのため、コレクションビューコントローラーを使うと画面いっぱいにコレクションビューが表示される。
コレクションビューを画面全体にしたくない場合は、コレクションビューコントローラーを使わずにコレクションビューの部品を使うのが望ましい。
コレクションビューコントローラーを使ってみる
コレクションビューコントローラーを使ってコレクションビューを表示してみよう。
以降の手順を開始する前のXcodeプロジェクトをGitHubに置いたので、試してみる人はご利用されたし。
⇒「テスト用プロジェクト」
事前準備ではView Controller(以下、ビューコントローラー)にNavigation BarとImage View(以下、イメージビュー)を配置し、タイトルと画像を表示するコードを記述しておいた(※事前準備の段階では実行時エラーになる)。
これにコレクションビューコントローラーを追加し、コレクションビューのアイテムをタップすると画面遷移してタイトルと画像が表示されるものを実装する。
ストーリーボードにコレクションビューコントローラーを配置する(下図赤矢印)。続いて、黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Is Initial View Controllerにチェックを入れる。これでアプリ起動時にコレクションビューコントローラーが起動されるようになった。
下図赤枠のセルを選択、黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Identifierに「TestCell」を入力する。これはソースコードからこのセルにアクセスするための識別子の設定である。
セルにImage View(以下、イメージビュー)を配置する(下図赤矢印)。続いて、黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Modeに「Aspect Fit」、Tagに「1」を設定する。
紫枠のPinボタンを押して吹き出しの設定画面を表示する。黄枠のConstraint to Marginsのチェックを外し、上下左右の4つの制約に「0」を入力する。これでイメージビューがセルの大きさに合わせて表示されるようになった。
次にコレクションビューコントローラーのカスタムクラスを作る手順に入る。
メニューから「File」⇒「New」⇒「File…」を選択する。
テンプレートを選択する画面が表示されるので、「iOSのSource」⇒「Cocoa Touch Class」を選択する。
クラス名を入力する画面が表示されるので、Classに「TestCollectionViewController」、Subclass ofに「UICollectionViewController」を入力し、Nextボタンを押す。
保存先を指定する画面が表示されるので、プロジェクトと同じ場所であることを確認し、Createボタンを押す。
ストーリーボードに戻り、下図赤枠のコレクションビューコントローラーを選択、黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Classに「TestCollectionViewController」を設定する。これでコレクションビューコントローラーにカスタムクラスが使われるようになった。
Ctrlキーを押しながら赤枠のコレクションビューコントローラーをドラッグ&ドロップでビューコントローラーまで運んで吹き出しのメニューを表示し、メニューから「Modal」を選択する。これは2つのコントローラーをセグエで接続する設定である。
下図赤枠のSegueを選択、黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Identifierに「TestSegue」を設定する。これはソースコードからセグエにアクセスするための設定である。
TestCollectionViewController.swiftを以下のコードに変更する。
セルが選択されたらセグエを実行し、「画面遷移前の呼び出しメソッド」の中で、セルの画像を遷移先ビューコントローラーのインスタンス変数に設定している。
Table View Controllerの場合と同様に、UICollectionViewControllerにはDataSourceとDelegateがすでに適用されているので、サブクラスで適用する必要が無い。そのため、デリゲートメソッドはオーバーライドして実装することになる。
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 |
// // TestCollectionViewController.swift // import UIKit class TestCollectionViewController: UICollectionViewController { //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() } //データの個数を返すメソッド override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 7 } //データを返すメソッド override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { //セルを取得し、イメージビューに画像を設定して返す。 let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCell", forIndexPath: indexPath) let imageView = cell.contentView.viewWithTag(1) as! UIImageView imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png") return cell } //セル選択時の呼び出しメソッド override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { //セグエを実行する。 performSegueWithIdentifier("TestSegue", sender: nil) } //画面遷移実行前の呼び出しメソッド override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { //選択中のセルの画像を取得する。 let index = collectionView?.indexPathsForSelectedItems()?.first let cell = collectionView?.cellForItemAtIndexPath(index!) let imageView = cell!.viewWithTag(1) as! UIImageView //遷移先のビューコントローラーを取得し、インスタンス変数に画像とテキストを設定する。 let controller:ViewController = (segue.destinationViewController as? ViewController)! controller.testTitle = String(index!.row) controller.testImage = imageView.image } } |
ViewControlloer.swiftは変更無し。
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 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testNavBar: UINavigationBar! @IBOutlet weak var testImageView: UIImageView! var testTitle:String! var testImage:UIImage! override func viewDidLoad() { super.viewDidLoad() //タイトルと画像を設定する。 testNavBar.topItem!.title = testTitle testImageView.image = testImage } //ボタン押下時の呼び出しメソッド @IBAction func pushButton(sender: UIBarButtonItem) { //モーダル表示されているビューコントローラーを解放する。 self.dismissViewControllerAnimated(true, completion:nil) } } |
以下は実際のプレイ動画