0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UICollectionViewCell をキレイに並べるのに苦労した話

Posted at

背景

UICollectionView 内に、1行につき4つずつセルを並べようとしてもなぜか画面の外まではみ出してしまい苦労したので解決方法を残します。

元のコード

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let sectionInsets = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset ?? .zero
    let interItemSpacing = 10.0 // セル間のスペース
    let numberOfItemsPerRow = 4.0
    
    // Safe Area を考慮した幅から、左右のインセットとセル間のスペースを引く
    let totalSpacing = sectionInsets.left + sectionInsets.right + (interItemSpacing * (numberOfItemsPerRow - 1))
    let availableWidth = collectionView.safeAreaLayoutGuide.layoutFrame.width - totalSpacing
    
    // セルの幅を計算
    let width = availableWidth / numberOfItemsPerRow
    return CGSize(width: width, height: 80)
}

原因

collectionView(_:layout:sizeForItemAt:) でセルのサイズを指定するだけでは、レイアウトが自動的に再描画されないためでした。
collectionView(_:layout:sizeForItemAt:) は、セルのサイズを要求されたときにそのサイズを提供するためのメソッドであり、再レイアウトや再描画をトリガーするメソッドではありません。

対応

viewDidLayoutSubviews() でレイアウトを無効化し、再度レイアウトを計算することで、最終的な正しいレイアウトが適用されます。
invalidateLayout() を呼び出すことで、コレクションビューが表示された後に正しいサイズで再レイアウトされます。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    // レイアウトを再計算
    collectionView.collectionViewLayout.invalidateLayout()
}
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?