LoginSignup
25
27

More than 5 years have passed since last update.

UICollectionViewでSelfSizingを行う

Last updated at Posted at 2016-08-19

UICollectionViewのsizeForItemAtIndexPathで高さを動的に設定(systemLayoutSizeFittingSize)していると、
セルの数が増えるにつれ動作がもっさりしてきたので、代わりになるものとしてSelfSizingを使ってみます。

今回は、セルの最大横幅あり、高さ可変で表示します。
ポイントは以下の4つです。

  1. estimatedItemSize(凡そのセルサイズ)を設定し、SelfSizingを有効にします
  2. 最大横幅を設定します(横幅が固定値であればAutoLayoutでWidthを設定するだけ?)
  3. AutoLayoutを上下左右に設定します(どこかが抜けると正しく表示されませんでした)
  4. 最大横幅に合わせて文字を折り返すようにLinesを0に設定します

実行結果
スクリーンショット 2016-08-20 00.52.41.png

上記のような画面を作っていきます。

SelfSizing有効化

estimatedItemSize(凡そのセルサイズ)を設定し、SelfSizingを有効にします。
実際のセルサイズに近い値を設定したほうがよさそうな気はしますが、とりあえずw1h1にしています。
w0h0にするとSelfSizingは有効になりません。

ViewController
import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    @IBOutlet var collectionView: UICollectionView!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        // Self-Sizingの有効化
        if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.estimatedItemSize = CGSizeMake(1, 1)
        }
    }

    // MARK: UICollectionViewDataSource
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        return 100
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! LabelCollectionViewCell
        cell.configureWithIndexPath(indexPath)
        return cell
    }
}

最大横幅設定

ラベルの最大横幅を設定します。

LabelCollectionViewCell
import UIKit

class LabelCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var label: UILabel!

    func configureWithIndexPath(indexPath: NSIndexPath)
    {
        // 枠組み
        layer.borderWidth = 1
        layer.borderColor = UIColor.blackColor().CGColor
        backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0)

        // テキスト作成
        label.text = labelTextWithNum(indexPath.item + 1)

        // 最大横幅設定 これが無いとエラーログが延々と…
        label.preferredMaxLayoutWidth = 50 //CGRectGetWidth(label.frame)
    }

    private func labelTextWithNum(num: Int) -> String
    {
        var text = "1"
        if num > 1 {
            for t in 2...num {
                text = text.stringByAppendingString(" \(t)")
            }
        }
        return text
    }
}

AutoLayout設定

上下左右全てにAutoLayoutを設定します。
スクリーンショット 2016-08-20 00.46.10.png

最大横幅に合わせて折り返し表示

ラベルのLinesを0に設定します。
スクリーンショット 2016-08-20 00.46.52.png

最後に

systemLayoutSizeFittingSizeでセルサイズを計算するより早いのかまだ検証してません。

参考

http://qiita.com/yuya_presto/items/08b0656f67a59c8c2d03
http://stackoverflow.com/questions/25947146/multiple-uilabels-inside-a-self-sizing-uitableviewcell

25
27
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
25
27