げっとシステムログ

WEB開発メモ

CollectionView の使い方

とりあえずものを表示させてみる

  • セルの設定を行う
  • 描画のためのコード
    • NSObject, UICollectionViewDataSource, UICollectionViewDelegate

セルの設定

セルに identifier を設定する

f:id:shun-fix9:20160501135228p:plain

カスタムクラスがあるならそれの設定も
(サンプルには載っていないけど、今回はラベルを幾つか配置しているのでカスタムクラスでやっている)

f:id:shun-fix9:20160501135244p:plain

セルの種類が幾つかある場合は、 Items の数を増やすと設定できるようになる

f:id:shun-fix9:20160501135330p:plain

outlet の設定

collectionView を outlet でコードに紐付ける

f:id:shun-fix9:20160501135536p:plain

collectionView を右クリックすると outlet のやつが出てくるので、 Referencing Outlets の部分から右側のコードまで引っ張って紐づけを行う

f:id:shun-fix9:20160501132414p:plain

右側のコードが別なやつだった場合は右上のパンくずリストみたいなやつから選びなおせる

描画のためのコード

if tasksDelegate == nil {
  tasksDelegate = TasksDelegate()
  taskCollection.delegate = tasksDelegate
  taskCollection.dataSource = tasksDelegate
}

collectionView に dataSource と delegate を設定する

ViewController に UICollectionViewDataSource と UICollectionViewDelegate を実装する、というサンプルが結構あるが、これは ViewController が一つの CollectionView しかもっていない場合に適切なもので、中に他のコンポーネントがある場合は別なクラスにするのが良いはず

というわけで DataSource クラスは別に用意する

import UIKit

class TasksDelegate : NSObject, UICollectionViewDelegate, UICollectionViewDataSource {

  private let tasks = [0,1,2,3]

  func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let task = tasks[indexPath.row]
    if task == 0 {
      return collectionView.dequeueReusableCellWithReuseIdentifier("blank", forIndexPath: indexPath)
    }

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath)
    if let taskCell = cell as? TaskCell {
      // セルの描画
    }
    return cell
  }

  func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
  }

  func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return tasks.count
  }
}

セクション一つ
task が 0 なら blank, そうでなれば cell を描画 という構成

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell が肝

  1. collectionView.dequeueReusableCellWithReuseIdentifier("blank", forIndexPath: indexPath) でセルを取得
  2. if let taskCell = cell as? TaskCell で目的のクラスにして描画

dequeueReusableCellWithReuseIdentifier の第一引数には、先に設定しておいた identifier を指定する
カスタムクラスを使用する設定にしておくと、このクラスにキャスト出来るようになる

これで、とりあえず表示だけはなんとかなるはず

セルがタップされたら背景画像を変える

そういうことをしてみたいと思った
ここでは、セルが選択された時にセルの背景画像のハイライトを反転させる、というやり方をしている
(正しい使い方かはわからぬ)

  func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? TaskCell {
      if let imageView = cell.backgroundView as? UIImageView {
        imageView.highlighted = !imageView.highlighted
      }
    }
  }

ストーリーボードでセルの背景画像を設定してやると backgroundView で取得できる

この UIImageView の highlighted のオン、オフでタップされたら画像を変える、ということをやってみた

まあ、うまくいっているように見える

ものが表示されない・・・というときは

  • CollectionView の背景、 Cell の背景を白、黒以外の色にしよう
  • 文字の色を白、黒以外の色にしよう

文字や背景色が親の色と一緒になって見えない、というハマり方をした
あと、 hidden になってたり、他の要素に隠れているのでは?という疑心暗鬼とか

例えば CollectionView の背景を赤にして、文字色を青にすれば、かなりきつい配色になるので表示されていないならすぐにわかる