Carousel Using UICollectionView
UICollectionView로 Carousel UI를 만들었습니다.
핵심
- 셀을 아이템 수보다 2개 더 만들어서
- > 첫 번째 아이템의 왼쪽에는 마지막 아이템의 복제 셀을,
- > 마지막 아이템의 오른쪽에는 첫 번째 아이템의 복제 셀을 표시합니다.
- 첫 번째 아이템에서 오른쪽을 스와이프하면 마지막 아이템의 복제 셀을 보여준 후 마지막 아이템의 진짜 셀로 애니메이션없이 이동시킵니다.
- 마지막 아이템에서 왼쪽으로 스와이프하면 첫 번째 아이템의 복제 셀을 보여준 후 첫 번째 아이템의 진짜 셀로 애니메이션없이 이동시킵니다.
if indexPath.item == cellIndexOfLastItem {
….if let rightCell = collectionView.cellForItem(at: IndexPath(item: cellIndexOfLastItem+1, section: 0)), collectionView.bounds.contains(collectionView.convert(rightCell.center, to: collectionView)) {
……..let xOfCellOfFirstItem = cell.frame.width
….….collectionView.contentOffset = CGPoint(x: xOfCellOfFirstItem, y: 0)
.…}
}
Fine Tuning
- 스와이프를 매우 빠르게 계속 하면 양끝에서 연결이 끊어지는 경우가 생깁니다. 복제 셀에서 진짜 셀로 이동할 때 scrollTo 메소드를 사용할 때 그렇습니다. contentOffset에 값을 직접 넣는 경우에는 그렇지 않습니다.
- 양 끝에서 스와이프를 힘차게 하면 연결된 셀이 가운데에서 멈추지 않는 경우가 생깁니다. 스크롤이 멈추면 위치를 보정해주면 괜찮아집니다.
let collectionViewCenter = collectionView.center
let cellCenter = collectionView.convert(cell.center, to: collectionView.superview)
let offsetX = collectionViewCenter.x — cellCenter.x
if offsetX != 0 {
collectionView.contentOffset = CGPoint(x: collectionView.contentOffset.x — offsetX, y: collectionView.contentOffset.y)
}
장점
- 이미 UICollectionView를 이용해서 페이지 처리를 하고 있다면 간단한 수정으로 Carousel을 만들 수 있습니다.
단점
- UICollectionView가 지원하지 않는 기능을 만들다 보니 양끝을 연결하는 동작이 매끄럽지 않아서 튜닝도 해야 하고,
- 실제 아이템은 N개인데 셀은 N+2개라서 이를 보정해줘야 합니다.
let item = items[itemIndex(withCellIndex: indexPath.item)]
대안
- 커스텀 뷰를 직접 만들수도 있습니다.
- https://jongwonwoo.medium.com/infinite-loop-view%EB%A5%BC-%EC%A0%90%EC%A7%84%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0-ios-swift-8fa53ef32593