SwiftのUICollectionViewのCellの高さには気をつけよう。タップが効かない時がある。

Swift Swift
Swift

UICollectionViewをCompositionaLayoutで実装し、コードでUIを作成した時の話。

きっかけはUIViewにTapGestureをつけても反応しない・・・

UICollectionViewのCellの中に配置されているUIViewに対して、UITapGestureRecognizerを設定し、タップ動作を行えるようにしました。

しかし、タップは反応せず・・・
「あれ?」他に設定が必要だったかな・・・

とか思って悩んでいました。

見た目も普通に見えており、特に問題ないように思っていました。
しかし、見た目に騙されてはいけませんでした・・・

このように表示されていたので、気づきませんでした。

色々試して確認していると、気付きました・・・

Cellの高さが足りてない!

どういう事かといいますと、見た目はCellの中身が全部入っているように見えるし、正常なのだと思っていました。
しかし、実際はこのような状態になっていました。

コードのみでレイアウトを作成し、AutoLayoutを使用してViewを配置していました。
その際に、Cellの高さを子要素に合わせて指定していなかった事により、実際の高さが反映されていなかったのです_| ̄|○ il||li

「え?見えてるやん。なんで??」
と思ってしまいましたが、そういうモノなのですね。

そして、タイトルに記載したように、タップが効かない。
これの原因が、このCellの高さが実際の高さに合っていないことによるものでした。

このように2個目のUILabelはCellの範囲を超えています。
見えてますけどね。|д゚)チラッ

見えているが、Cellの高さは超えて配置されている。
そのため、2個目のUILabelのタップが動作しません。
1個目のUILabelも、1個目のUILabelにタップ動作を付けた場合、Cell内に収まっている部分(1個目のUILabelの上の方)はタップが反応します。
しかし、下の方は反応しません。

このような現象になります。
見た目が正常なだけに、なぜタップが反応しないのか?原因を理解するのに時間がかかってしまいました・・・

正常に動作するために書いたコード

class CustomCellName: UICollectionViewCell {
    
    let label1 = UILabel()
    let label2 = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        label1.text = "label1"
        label2.text = "label2"
        
        label1.translatesAutoresizingMaskIntoConstraints = false
        label2.translatesAutoresizingMaskIntoConstraints = false

        label1.addSubview(captionLabel)
        label2.addSubview(bodyLabel)

        label1.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16).isActive = true
        label1.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16).isActive = true
        label1.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16).isActive = true
        label1.heightAnchor.constraint(equalToConstant: 200).isActive = true

        label2.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16).isActive = true
        label2.topAnchor.constraint(equalTo: label1.bottomAnchor, constant: 16).isActive = true
        label2.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16).isActive = true
        label2.heightAnchor.constraint(equalToConstant: 200).isActive = true
        
        // この記述でCellの高さを子要素に合わせている
        contentView.bottomAnchor.constraint(equalTo: label2.bottomAnchor).isActive = true
    }
    
}

説明に必要なコードのみ記載してます。
こちらのようなコードで最終的にレイアウトしました。

Cellの高さつけるために、UILabelの下部分にCellの下部がくるように指定しています。
これで配置されているUILabelすべてのタップが正常に動きました。

ちなみに、間違った記述の時に変な動きをしている部分がありました。
それを正常に理解していれば、もっと早く気付けたかも・・・

UICollectionViewを上にドラッグしてスクロールした時(指を画面の上の方に動かす動作)にCellが消えてしまう現象が発生していました。

後から考えると、Cellの高さが実際より小さいので、Cellの中に配置されているUILabelなどが見えている状態なのに、Cellの描画がされなくなった・・・のかな?と思われる現象が起きていました。

コメント

タイトルとURLをコピーしました