이 포스트는 UICollectionView의 Carousel View로 만든 배너를 무한하게 스크롤하게 만들기 위한 포스팅입니다 :)
(참고: [Swift] 배너 만들기(Make a Slide banner with Carousel))
Carousel은 우리말로 회전목마를 뜻합니다.
Carousel View는 일정한 형태를 유지하며 무한히 회전하는 View를 말하지만, 일정하게 Slide 되는 View를 칭하기도 합니다.
최종 수정일 - 22. 09. 20 PM 1:20
개요
1. 기존의 셀에서 앞 뒤에 2개의 셀을 추가해준다.
2. 추가 영역에 도달하면 해당 데이터와 원본 데이터가 동일한 셀로 이동한다.
- 7번 셀에 도달한다면 스크롤을 2번 셀로 이동한다.
- 1번 셀에 도달한다면 스크롤을 6번 셀로 이동한다.
3. 추가 데이터 없이 무한히 스크롤이 가능하다.
방법
1. 이전 포스팅에서 만든 UICollectionView 생성
더보기
@IBOutlet weak var collectionView: UICollectionView!
var cellSize: CGSize = .zero
let minimumLineSpacing: CGFloat = 8
let data: [UIColor] = [.systemRed, .systemBlue, .systemGreen, .lightGray, .darkGray]
func setupCollectionView() {
cellSize = CGSize(width: UIScreen.main.bounds.width - (minimumLineSpacing * 4), height: 128)
collectionView.delegate = self
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return minimumLineSpacing
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
cell.backgroundColor = data[indexPath.row]
return cell
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let cellWidthIncludingSpacing: CGFloat = cellSize.width + minimumLineSpacing
let estimatedIndex = scrollView.contentOffset.x / cellWidthIncludingSpacing
let index: Int
if velocity.x > 0 {
index = Int(ceil(estimatedIndex))
} else if velocity.x < 0 {
index = Int(floor(estimatedIndex))
} else {
index = Int(round(estimatedIndex))
}
targetContentOffset.pointee = CGPoint(x: (CGFloat(index) * cellWidthIncludingSpacing) - (minimumLineSpacing * 2), y: 0)
}
2. 앞 뒤에 셀 추가하기
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let numberOfItems = 2 + data.count + 2
return numberOfItems
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
let numberOfItems = 2 + data.count + 2
// 반복되는 것처럼 보여야 하므로 위 사진과 같이 보이도록 데이터를 넣어준다.
switch indexPath.row {
case 0:
cell.backgroundColor = data[data.count - 2]
case 1:
cell.backgroundColor = data[data.count - 1]
case numberOfItems - 2:
cell.backgroundColor = data[0] // 예) 뒤에서 두번째 셀에는 첫번째 데이터가 보이도록 한다.
case numberOfItems - 1:
cell.backgroundColor = data[1]
default:
cell.backgroundColor = data[indexPath.row - 2]
}
return cell
}
3. 셀의 시작 위치 변경
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// 최초 시작 셀은 실제 데이터의 첫번째가 오는 3번째 셀부터 보이도록 한다.
collectionView.reloadData()
collectionView.setContentOffset(CGPoint(x: contentOffsetX(for: 2), y: 0), animated: false)
}
func contentOffsetX(for index: Int) -> CGFloat {
let cellWidthIncludingSpacing: CGFloat = cellSize.width + minimumLineSpacing
return (CGFloat(index) * cellWidthIncludingSpacing) - (minimumLineSpacing * 2)
}
4. 추가 영역에 도달하면 스크롤 위치 변경하기
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset
let numberOfItems = 2 + data.count + 2
// 동일한 데이터를 가진 셀로 이동하도록 ContentOffset 변경
if contentOffset.x > contentOffsetX(for: numberOfItems - 2) {
collectionView.setContentOffset(CGPoint(x: contentOffsetX(for: 2), y: 0), animated: false)
} else if contentOffset.x < contentOffsetX(for: 1) {
collectionView.setContentOffset(CGPoint(x: contentOffsetX(for: numberOfItems - 3), y: 0), animated: false)
}
}
'iOS > Swift' 카테고리의 다른 글
[Swift] UICollectionView Custom Layout: A Spinning Wheel with Swift 5 (0) | 2022.11.04 |
---|---|
[Swift] 배너 만들기(Make a Slide banner with Carousel) (1) | 2022.09.19 |
[Swift] UILabel 생략 부호(... 또는 Ellipsis) 바꾸기 (0) | 2022.09.01 |
[Swift] textViewDidChange(_:) 위치값 초기화 현상 수정 (0) | 2022.08.22 |
[Swift] 화면 눌러서 키보드 내리기 (Tap to hide keyboard) (0) | 2022.08.12 |