본문 바로가기

Project/PhotoDiary

👌 컬렉션뷰내의 셀의 위치를 가운데로 오게 하는 방법

class CenterSnapFlowLayout: UICollectionViewFlowLayout {
    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        guard let collectionView = self.collectionView else { return proposedContentOffset }


		// ✅ 지금 제안된 위치에서 보여질 셀들의 범위를 계산합니다. 이 범위 내의 셀들 중에 가장 중앙에 가까운 셀을 찾기 위해 사용됩니다.
        let collectionViewSize = collectionView.bounds.size
        let proposedRect = CGRect(origin: proposedContentOffset, size: collectionViewSize)

	    // ✅ 이 범위 안에서 모든 셀의 레이아웃 정보(attributes) 를 가져옵니다.
        guard let layoutAttributes = super.layoutAttributesForElements(in: proposedRect) else {
            return proposedContentOffset
        }

        // ✅ collectionView의 화면 중앙 X 좌표를 계산합니다. 이 좌표에 가장 가까운 셀을 중앙으로 정렬하려고 해요
        let centerX = proposedContentOffset.x + collectionView.bounds.width / 2

        // ✅ 모든 셀을 돌면서: 각 셀의 중앙 위치(itemCenterX)와 화면 중앙(centerX) 사이의 거리(offset) 를 계산합니다. 
        // ✅ 이 중에서 가장 가까운 셀을 찾습니다. 
        // ✅ 그리고 그 셀을 화면 정가운데 오게 만들기 위해 minOffsetAdjustment 값을 계산합니다.
        var minOffsetAdjustment = CGFloat.greatestFiniteMagnitude
        for attributes in layoutAttributes {
            let itemCenterX = attributes.center.x
            let offsetAdjustment = itemCenterX - centerX
            if abs(offsetAdjustment) < abs(minOffsetAdjustment) {
                minOffsetAdjustment = offsetAdjustment
            }
        }

        return CGPoint(x: proposedContentOffset.x + minOffsetAdjustment, y: proposedContentOffset.y)
    }
}

 

UICollectionViewFlowLayout은 스크롤 후 어느 위치에서 멈출지를 targetContentOffset(forProposedContentOffset:) 메서드에서 계산

 

 

🧊 예시로 이해하기

  • 예를 들어 화면 너비가 400이고 셀 중앙이 각각 150, 350, 550, 750 이라면,
  • 스크롤 시 proposedContentOffset.x가 300이라고 하면,
  • centerX = 300 + 200 = 500이 됩니다.
  • 가장 가까운 셀은 550 이니까 offset = 550 - 500 = 50
  • 그래서 최종 offset = proposedContentOffset.x + 50 = 350
  • 👉 즉, 스크롤은 350으로 이동하게 되며, 셀 중앙(550)은 화면 중앙(500)에 딱 맞게 위치!