UICollectionViewを使ったタグクラウド風の表示

## まず普通にコレクションビューを作成
ストーリーボードで作成
![スクリーンショット 2019-03-08 3.25.10.png](https://qiita-image-store.s3.amazonaws.com/0/266239/05ce758d-5f61-b725-0788-63a0f7101053.png)  

```ViewController.swift

class ViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!

    let items = ["スイーツ", "パン", "スイーツ", "カフェ", "金沢", "駅前寿司", 
                 "祇園", "嵐山", "天満", "七本槍", "鶴橋", "灘", "篠山", 
                 "長浜ラーメン", "彦根", "奈良町", "ひがし茶屋街", "尾道", 
                 "ランチ", "おばんざい", "寿司", "焼肉", "カレー", "パスタ", 
                 "お好み焼き", "越前そば", "チョコレート", "手みやげ", "和雑貨", 
                 "文具", "本屋", "酒蔵", "パワースポット", "城下町", 
                 "庭園", "アート", "フォトジェニック", "絶景"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

extension ViewController: UICollectionViewDelegateFlowLayout {
    // セクションヘッダのサイズ
    func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize.zero
    }
}


extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCell", for: indexPath) as! ItemCell
        cell.label.text = self.items[indexPath.row]
        cell.layer.masksToBounds   = true
        cell.layer.cornerRadius    = 14
        return cell
    }
}
```

セルはこんな感じ
![スクリーンショット 2019-03-08 3.25.55.png](https://qiita-image-store.s3.amazonaws.com/0/266239/620b5e9b-f363-dd09-cd1d-7b030a7786f3.png)

```ItemCell.swift
import UIKit

class ItemCell: UICollectionViewCell {
    @IBOutlet weak var label: UILabel!
}
```

実行すると
<img src="https://qiita-image-store.s3.amazonaws.com/0/266239/17a3a222-88b0-b8a1-b2e6-2da199073353.png" width="300">

## UICollectionViewFlowLayoutを指定する
これだと等間隔の表示なので UICollectionViewFlowLayout を入れて調整する

```ViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let layout = UICollectionViewFlowLayout() 
        layout.scrollDirection = .vertical
        layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        layout.minimumInteritemSpacing = 10
        layout.minimumLineSpacing = 10
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        self.collectionView.collectionViewLayout = layout
    }
```

今度は狭すぎ
<img src="https://qiita-image-store.s3.amazonaws.com/0/266239/90e50893-4020-6ab8-a01a-9b1ec69632c7.png" width="300">

## セルのサイズを指定してみる
セルのラベルをsizeToFit()、横幅+30px、高さ40px にしてみる

```ViewControler.swift
extension ViewController: UICollectionViewDelegateFlowLayout {

    // セクションヘッダのサイズ
    func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize.zero
    }

    // セルのサイズ
    func collectionView(_: UICollectionView, layout _: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let label = UILabel(frame: CGRect.zero)
        label.font = UIFont.systemFont(ofSize: 14)
        label.text = self.items[indexPath.row]
        label.sizeToFit()
        let size = label.frame.size
        return CGSize(width: size.width + 30, height: 40)
    }
}
```

それっぽくなってきた！
<img src="https://qiita-image-store.s3.amazonaws.com/0/266239/8daa901a-fac6-d3ed-684e-d37be0899556.png" width="300">


## セルを左詰にするFlowLayoutを作成
空いているスペースを左詰めするためにFlowLayoutクラスを作成してみる
UICollectionViewLayoutAttributesというセルを表示する領域みたいなのが super.layoutAttributesForElements(in: rect) で取れる。
この中で各セルのX位置を算出して調整。
セルの長さ的に１行に入るなら1行に入るようにする。

```ViewControler.swift
class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect)

        var leftMargin = sectionInset.left
        var maxY: CGFloat = -1.0
        attributes?.forEach { layoutAttribute in
            if layoutAttribute.representedElementCategory == .cell {
                if layoutAttribute.frame.origin.y >= maxY {
                    leftMargin = sectionInset.left
                }
                layoutAttribute.frame.origin.x = leftMargin
                leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
                maxY = max(layoutAttribute.frame.maxY, maxY)
            }
        }
        return attributes
    }
}
```

これをコレクションに指定する。

```ViewControler.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let layout = LeftAlignedCollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        layout.minimumInteritemSpacing = 10
        layout.minimumLineSpacing = 10
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        self.collectionView.collectionViewLayout = layout

    }
```

できた！

<img src="https://qiita-image-store.s3.amazonaws.com/0/266239/e4683ffd-5a26-d56c-16ba-89328277d7c4.png" width="300">

[https://github.com/katafuchix/CollectionViewTagCloud](https://github.com/katafuchix/CollectionViewTagCloud)