article thumbnail image
Published 2023. 7. 23. 16:00

 

이번 포스팅에선 아래와 같이 무한히 스크롤되는 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

https://younggyun.tistory.com/30

복사했습니다!