【Swift】CollectionViewの使い方

このページでは、UICollectionViewを使ってデータを表示するまでの基本的な流れについて解説していきます。

UITableViewと少し似ているので、こちらの使い方が理解できていれば、UICollectionViewも理解しやすいです。

CollectionViewの設定をする

まずはStoryboard上にCollectionViewを設置して、色々設定を行います。

1. Collection Viewの設置

Objects一覧から「Collection View」を検索して、それをViewControllerにドラッグ&ドロップします。

2. Outletsの設定

続いて、CollectionViewのOutletsを設定します。

これを設定することで、セルの設定やセルへの値の代入などができるようになります。

やり方は、次の写真のように、Document OutlineでCollection ViewをControlキーを押しながらクリックし、ViewControllerにドラッグ&ドロップします。

すると、下のようにOutletsの画面が表示されるので、「dataSource」と「delegate」を選択します。

きちんと選択できている場合は、次の写真のように「dataSource」と「delegate」の左端に白丸が付きます。



CollectionViewCellの設定をする

続いて、セルの設定をしていきます。

1. IDの設定

Collection Viewを設置すると自動的にCollectionViewCell(セル)も追加されるので、このセルをクリックし、セルの名前に当たるID(Identifier)を設定します。

ID名は何でもいいですが、わかりやすいものにしておきましょう。

ここでは「Cell」としておきます。

2. セルにUILabelをセットする

今回はセルにラベルを置いて、それを表示する例を紹介するためUILabelをセルの中に起きます。

セルの真ん中に来るように、AutoLayoutの設定もしておきましょう。

3. tagの設定

後ほど、tagを使ってUILabelにデータをセットするので、tagに番号を振っておきます(今回は1とします)。

MEMO

今回の例はUILabel1つだけですが、セルの中に複数のUI部品を設置する場合は、それぞれ別のタグ番号を指定してください。

4. Estimate Sizeの設定

セルが1つのときに、Estimate Sizeが悪さをしてなのか中央に寄ってしまうことがあります。

それが嫌な場合、こちらの設定をNoneにしておきましょう。

5. セル同士の余計なスペースを0にしておく

デフォルトではセル間に余計な余白が入っています。

余白は自分で設定したいので、下の「Min Spacing」という項目を0にします。

以上で、セルの設定は完了です。

次はコードを書いていきます。


ViewControllerへの記述

ここでは、Storyboard上で設定したCollectionViewを表示するための処理を記述します。

コードは次のようになります。

import UIKit

class ViewController: UIViewController {

       // 1.セルに表示するデータを準備   let titleLabels: [String] = ["title1", "title2", "title3", "title4"]          override func viewDidLoad() {         super.viewDidLoad()                     } } // 2 collectionViewに関する設定 extension ViewController: UICollectionViewDataSource {           // 2-1. セクション数     func numberOfSections(in collectionView: UICollectionView) -> Int {         return 1     }          // 2-2. セル数     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {         return titleLabels.count     }          // 2-3. セルに値をセット     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {               // widthReuseIdentifierにはStoryboardで設定したセルのIDを指定         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)                  // セルのラベルに値をセット。viewWithTagにはタグの番号を指定         let title = cell.contentView.viewWithTag(1) as! UILabel         title.text = titleLabels[indexPath.row]         // セルに枠線をセット         cell.layer.borderColor = UIColor.lightGray.cgColor // 外枠の色         cell.layer.borderWidth = 1.0 // 枠線の太さ                  return cell     } } // 3. セルがタップされた時の処理など(今回は割愛) extension ViewController: UICollectionViewDelegate {     }

1. セルに表示するデータを準備

まずはセルに表示するためのデータが必要なので、テスト用に配列を用意しておきます。

 // 1.セルに表示するデータを準備
let titleLabels: [String] = ["title1", "title2", "title3", "title4"]

2. collectionViewの表示に関連する処理

続いて、collectionViewの表示に関連するプロトコル「UICollectionViewDataSource」を追加します。

class ViewController: UIViewController, UICollectionViewDataSource{}」のように書いてもいいのですが、数が増えると、可読性が悪くなるのでextensionで別出ししましょう。

// 2. テーブルビューに関する設定
extension ViewController: UICollectionViewDataSource {  

}

中には次の3つのメソッドを書きます。

// 2-1. セクション数
func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}
    
// 2-2. セル数
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return titleLabels.count
}
    
// 2-3. セルに値をセット
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {        
    // widthReuseIdentifierにはStoryboardで設定したセルのIDを指定
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        
    // セルのラベルに値をセット。viewWithTagにはタグの番号を指定
    let title = cell.contentView.viewWithTag(1) as! UILabel
    title.text = titleLabels[indexPath.row]

    // セルに枠線をセット
    cell.layer.borderColor = UIColor.lightGray.cgColor // 外枠の色
    cell.layer.borderWidth = 1.0 // 枠線の太さ
        
    return cell
}

「2-1」はセクションの数を返します。今回は1つだけなので、return 1としています。

「2-2」はデータを表示するセル数を返しています。配列titleLabelsの要素数必要なので、「titleLabels.count」を返しています。

「2-3」では、セルに表示する値をセットしています。

まず、collectionView.dequeueReusableCell(withReuseIdentifier: “Cell”, for: indexPath) でセルを作成し、そのセルに配列titleLabelsの値を格納して返却しています。

「indexPath.row」はセルの行数を表します。

以上で、ビルドしシミュレーターを起動すると、次のように四角のセルが4つ表示されましたが、バランスが悪く見栄えはよくありません。

 

そのため、次にセルのサイズの調整を行う必要があります。

3. セルのサイズを調整する

セルのサイズ調整には、UICollectionViewDelegateFlowLayoutを使います。これを使うことで画面サイズに合ったセルサイズを計算することができます。

以下のコードを追加してください。

// セルのサイズを調整する
extension ViewController: UICollectionViewDelegateFlowLayout {

    // セルサイズを指定する
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        // 横方向のサイズを調整
        let cellSizeWidth:CGFloat = self.view.frame.width/2
    
        // widthとheightのサイズを返す
        return CGSize(width: cellSizeWidth, height: cellWidth/2)
    }        
}

今回は横2列でセルを並べたいので、「self.view.frame.width/2」でスクーンの半分のサイズを取得し、それをreturn CGSize()で返しています。

縦の高さは、横幅の半分にしました。

これでシミュレーターを立ち上げてみると、以下のようにバランスよくセルが配置されています。

行間を指定したい場合

行間を設定したい場合は、UICollectionViewDelegateFlowLayout 内に次の処理を加えます。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
     return 15.0 // 行間
}

セルに余白を持たせたい場合

セルに余白を持たせたい場合は、UICollectionViewDelegateFlowLayout 内に次の処理を加えます。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
  return UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
}

ただし、上記の例の場合、左右の余白が15ずつ(合計30増える)ので、セルのwidthのサイズを30引いてあげないと、1列で表示されてしまうので注意してください。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

   let cellSizeWidth:CGFloat = self.view.frame.width/2 - 30  // 余白分(30)を引く
   return CGSize(width: cellSizeWidth, height: cellSizeWidth/3)
}

セクションごとにヘッダーを付けたい場合

以下の記事で解説しています。

【Swift】CollectionViewにヘッダーをつける方法

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA