酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

UICollectionViewのカスタムセル上のViewが綺麗な正円形にならない

(2019/09/14追記)大昔に「UICollectionViewの初期表示時にズレる - 酢ろぐ!」でも同じ現象でハマっていたらしい。

UICollectionViewのカスタムセル上のViewが綺麗な正円形にならない

UICollectionViewでAuto Layoutを使ったカスタムセル上で円形のViewを表示する時に、タイミングによってViewが綺麗な円形にならず楕円形になってしまいます。

f:id:ch3cooh393:20190510082808p:plain

レイアウト計算後の結果がCellのcontentViewに反映されておらず、contentViewとcellのサイズが異なるために発生してしまうのですが、一度実装したらそのプロジェクトではそのまま発生しなくなるので、思い出したかのように数年に一度発生して、その都度ぐぐって修正している気がする。

UICollectionViewで固定カラム数でセルを表示させたい場合、セルのサイズは可変サイズにします。どの開発者も一度は経験しているかと思います。方法はいくつかありますが、個人的には「Auto Layoutに準拠したUICollectionViewCellのサイジング - Qiita」の方法が一番しっくりときます。*1

f:id:ch3cooh393:20161122211131j:plain
Auto Layoutに準拠したUICollectionViewCellのサイジングより引用

猫ちゃん画像を正円形したい場合、下記のようなコードを書くかもしれません。ただし、これだけではタイミングによっては、UIImageViewは正円形にならずに楕円形になってしまいます。

    var item: UIImage? {
        didSet {
            updateDisplay()
        }
    }

   func updateDisplay() {
        mainImageView.layer.masksToBounds = true
        mainImageView.layer.cornerRadius = mainImageView.frame.width / 2
        mainImageView.image = item
    }

UIImageViewに対して、layer.masksToBoundslayer.cornerRadiusを指定する前に、contentViewのサイズをセルと同じにしておきます。

    var item: UIImage? {
        didSet {
            updateDisplay()
        }
    }

   func updateDisplay() {
        contentView.frame = bounds
        mainImageView.layoutIfNeeded()

        mainImageView.layer.masksToBounds = true
        mainImageView.layer.cornerRadius = mainImageView.frame.width / 2
        mainImageView.image = item
    }

これで猫ちゃん画像は、綺麗な正円形になります。

参考記事

関連記事

このほかにもiOSアプリ開発で見つけたネタや悩んだ内容など紹介しています。Tipsをまとめておりますのでこちらのページをご参照ください。

*1:画像の下のURLを省略せずに全文表示して、一列のすべてのセルを一番高いheightに合わせたい場合にはこの方法は使えません。