[iOS]タグ一覧っぽい左上詰めのUICollectionView

## 結果

左上から詰めるようなよくあるViewですが、レイアウトが無いので自分で組まなきゃいけないという、個人的に萎えるパーツの代表格です。（確かAndroidなら割と簡単ですよね）
<img width="300" alt="Simulator Screen Shot" src="https://qiita-image-store.s3.amazonaws.com/0/20784/e17543e8-b0f4-d153-c473-56b6a926ce3d.png">

私はこれまで3回組んでいますが、もういい加減このViewに時間を掛けるのがいやになったのでパーツ化しました。（たぶんどこかで既出だと思いますが）

コードはこちら
https://github.com/osanaikoutarou/TagsViewSample

もちろんdidSelectItemAtIndexPathで選択可能です

## どのようにパーツ化するか

cellSizesと、horizontalMarginと、verticalMargin、そして全体の枠であるinsetを、カスタムLayoutに設定します。

```swift

let layout = TagsCollectionViewLayout()

// 呼び出し
layout.setup(cellSizes: cellSizes,
             horizontalMargin: 10,
             verticalMargin: 10,
             collectionViewInset: UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 15))

collectionView.setCollectionViewLayout(layout, animated: false)

```

中身はゴニョゴニョ計算しています

```swift
/// レイアウトを指定,左上詰めで計算する
///
/// - Parameters:
///   - cellSizes:左上から順のサイズ
///   - horizontalMargin: cell同士のmargin 上下
///   - verticalMargin: cell同士のmargin 左右
///   - collectionViewInset: 全体のInset
func setup(cellSizes:[CGSize], horizontalMargin:CGFloat, verticalMargin:CGFloat, collectionViewInset:UIEdgeInsets) {
    self.cellSizes = cellSizes
    self.horizontalMargin = horizontalMargin
    self.verticalMargin = verticalMargin
    self.collectionViewInset = collectionViewInset
        
    // 左上から並べていきます
        
    var currentPoint:CGPoint = CGPoint(x: collectionViewInset.top, y: collectionViewInset.left)
    var currentRowHeight:CGFloat = 1
        
    for (i, size) in cellSizes.enumerated() {
        let indexPath = IndexPath(row: i, section: 0)
            
        if (currentPoint.x + size.width <= collectionViewWidth - collectionViewInset.left - collectionViewInset.right) {
            // 収まる
            let frame = CGRect(x: currentPoint.x, y: currentPoint.y, width: size.width, height: size.height)
            cellFrames[indexPath] = frame
                
            if (currentRowHeight < size.height) {
                currentRowHeight = size.height
            }
            currentPoint.x += size.width + horizontalMargin
        }
        else {
            // 改行したうえで
            currentPoint.x = collectionViewInset.left
            currentPoint.y += currentRowHeight + verticalMargin
            currentRowHeight = 1
                
            if (currentPoint.x + size.width <= collectionViewWidth - collectionViewInset.left - collectionViewInset.right) {
                // 収まる
                let frame = CGRect(x: currentPoint.x, y: currentPoint.y, width: size.width, height: size.height)
                cellFrames[indexPath] = frame
                    
                if (currentRowHeight < size.height) {
                    currentRowHeight = size.height
                }
                currentPoint.x += size.width + horizontalMargin
            }
            else {
                // 収まらない
                currentPoint = CGPoint(x: 0, y: currentPoint.y + verticalMargin + currentRowHeight)
                currentRowHeight = 1
                    
                let frame = CGRect(x: currentPoint.x,
                                   y: currentPoint.y,
                                   width: collectionViewWidth,
                                   height: size.height)
                cellFrames[indexPath] = frame
                    
                if (currentRowHeight < size.height) {
                    currentRowHeight = size.height
                }
                currentPoint.x = collectionViewInset.left
            }
        }
    }
}

```

任意の位置にセルを配置するための方法については、毎度こちらを参考にしています。
ありがとうございます。
https://dev.classmethod.jp/smartphone/iphone/ios6-uicollectionview-customlayout/

## cellSizesには何を渡すか

横幅が無制限だった際のcellSizeです
例えば長い文章だとwidthが1000などになるかもしれません。そのまま渡せば良いように計算します

## 積み残し　TODO

・改行処理（2行で表示したいなど）
・複雑なUIの場合
・もっとパーツ然としていたほうが良いですかね？