概要
UICollectionViewのcellサイズを中のコンテンツサイズに応じて自動調整する。
下イメージではUIButtonを横スクロールするUICollectionViewに並べた。UIButtonのサイズだけ、cellの横幅を自動調整している。
estimatedItemSizeを指定すると楽に設定することができる。TableViewのtableView.rowHeight = UITableViewAutomaticDimension
のようなもの。
UICollectionViewとUICollectionViewCellはstoryboardに配置されているものとする。
前提
cell内に配置する各Viewの配置位置を適切にautolayoutで配置しておく。例えば、配置するUIButtonはtop,bottom,left,rightともにcell幅一杯に配置するなど。
設定
collectionViewLayout.estimatedItemSize
にUICollectionViewFlowLayout.automaticSize
を設定する。estimatedItemSizeはUICollectionViewFlowLayoutにダウンキャストしないと参照できない。
override func viewDidLoad() { super.viewDidLoad() if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize } }
cell自体の制約を定義
cell自体の制約を定義を行わないとサイズが調整されない。
対象cellのクラスファイルを作成し、awakeFromNib()
メソッドに以下の定義を追加する。
storyboard上のオブジェクトに対しての紐付けも忘れずに。
class CollectionViewCell: UICollectionViewCell { override func awakeFromNib() { super.awakeFromNib() self.contentView.translatesAutoresizingMaskIntoConstraints = false let leftConstraint = self.contentView.leftAnchor.constraint(equalTo: self.leftAnchor) let rightConstraint = self.contentView.rightAnchor.constraint(equalTo: self.rightAnchor) let topConstraint = self.contentView.topAnchor.constraint(equalTo: self.topAnchor) let bottomConstraint = self.contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor) NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint]) } }
参考
UICollectionViewFlowLayoutのestimatedItemSizeを指定するとiOS12で表示がおかしい - Qiita
付録 自動調整したcell内のviewに余白をとりたい
cell内viewのサイジングは制約確定前に行う必要があるみたい。storyboardやViewController側で行うとおかしな挙動になった。
class CollectionViewCell: UICollectionViewCell { @IBOutlet weak var tagNameButton: UIButton! override func awakeFromNib() { super.awakeFromNib() //余白の調整処理 button.contentEdgeInsets = UIEdgeInsets(top: 5.0, left: 7.0, bottom: 5.0, right: 7.0) button.titleLabel?.adjustsFontSizeToFitWidth = true self.contentView.translatesAutoresizingMaskIntoConstraints = false let leftConstraint = self.contentView.leftAnchor.constraint(equalTo: self.leftAnchor) let rightConstraint = self.contentView.rightAnchor.constraint(equalTo: self.rightAnchor) let topConstraint = self.contentView.topAnchor.constraint(equalTo: self.topAnchor) let bottomConstraint = self.contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor) NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint]) } }