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)에 딱 맞게 위치!
'Project > PhotoDiary' 카테고리의 다른 글
🎶 이미지 테두리에 만드는 방법 (0) | 2025.06.25 |
---|---|
✅ A 이미지 위에 B 이미지를 올리고, 이동 범위를 이미 A 이미지 사이즈내로 하는 방법 (0) | 2025.06.24 |
👍 사용자가 버튼을 눌렀을 때 현재 보여지고 있는 시트(DiarySheetViewController)를 닫고, 그 이후에 PhotoDiaryViewController를 전체화면으로 띄우기 위한 흐름 (0) | 2025.06.16 |