이번 포스팅에선 아래와 같이 무한히 스크롤되는 Infinite Carousel을 구현해보자.
전체 코드는 여기에서 확인해볼 수 있다.
Collection View
우선 CollectionView를 생성해보자.
private let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal // 스크롤 방향 설정
/// CollectionView를 생성할 때 layout을 Initialized해주어야 한다.
let collectionView = UICollectionView(
frame: .zero,
collectionViewLayout: layout
)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.showsHorizontalScrollIndicator = false // 스크롤 indicator없애기
collectionView.isPagingEnabled = true // pageEnabled
collectionView.register(
UICollectionViewCell.self,
forCellWithReuseIdentifier: "Cell"
)
return collectionView
}()
다음으로는 스크롤의 방향을 Horizontal로 설정해주고
Page Enabled 프로퍼티를 True로 설정해준다.
추가적으로 자연스러운 Paging을 위해서 Cell간의 간격을 0으로 설정해주자.
private let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 0
...
}()
다음으로는 UICollectionViewDelegateFlowLayout를 통해 Cell의 크기를 CollectionView의 크기로 맞추어 보자.
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
return CGSize(
width: self.collectionView.frame.width,
height: self.collectionView.frame.height
)
}
}
Infinite Carousel
Inifite Carousel은 약간의 트릭이 필요하다.
무한스크롤을 구현하기 위해선,
0번의 이미지를 마지막에
마지막 이미지를 맨앞에 추가해주어야 한다.
viewModel.output.images
.map { images in
guard
let first = images.first,
let last = images.last
else {
return images
}
var appendItems = images
/// Add last Image to First, Add first Image to Last
appendItems.insert(last, at: 0)
appendItems.append(first)
return appendItems
}
/// collectionView Cell 등록
.drive(collectionView.rx.items(
cellIdentifier: "Cell",
cellType: UICollectionViewCell.self
)) { (_, item, cell) in
cell.backgroundView = UIImageView(image: item)
}
.disposed(by: disposeBag)
그런다음,
scrollViewDidEndDecelarting(_:)메서드를 통해
1번 Cell에서 0번 Cell로 이동했을 경우 scrollToItem 메서드를 사용해서 3번 Cell로 이동 시켜준다.
if page == 0 {
collectionView.scrollToItem(
at: IndexPath(item: imagesCount, section: 0),
at: .right,
animated: false
)
}
반대의 경우도 마찬가지이다.
3번 Cell에서 4번 Cell로 이동했을 경우 scrollToItem 메서드를 통해 1번 Cell로 이동 시켜준다.
else if page == imagesCount + 1 {
collectionView.scrollToItem(
at: IndexPath(item: 1, section: 0),
at: .right,
animated: false
) page = 1
}
마지막으로 ViewDidLoad메서드에서 CollectionView를 1번째 Cell로 이동시켜주면 된다.
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
DispatchQueue.main.async {
self.collectionView.scrollToItem(
at: IndexPath(item: 1, section: 0),
at: .right,
animated: false
)
}
}
Reference
'iOS > iOS' 카테고리의 다른 글
[iOS] Local DB(2) - Core Data Concept (0) | 2023.10.09 |
---|---|
[iOS] Local DB(1) - UserDefaults, Keychain (0) | 2023.10.04 |
[iOS] Floating Custom TabBarController (0) | 2023.07.22 |
[iOS] Modularization(2) - Loose Coopling (0) | 2023.05.18 |
[iOS] Modularization(1) - Library, Framework, Swift Package (0) | 2023.05.04 |