LoginSignup
24
16

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-03-07

まず普通にコレクションビューを作成

ストーリーボードで作成
スクリーンショット 2019-03-08 3.25.10.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

ItemCell.swift
import UIKit

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

実行すると

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
    }

今度は狭すぎ

セルのサイズを指定してみる

セルのラベルを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)
    }
}

それっぽくなってきた!

セルを左詰にするFlowLayoutを作成

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

    }

できた!

https://github.com/katafuchix/CollectionViewTagCloud

24
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
16