iOS/UIKIT

collectionView, pageControl 사용

밤새는 탐험가89 2024. 7. 2. 12:52

 

구현 내용

  • 이미지를 가로 방향으로 스크롤하면 넘어가게 한다. 
  • 이때, 이미지 밑에 "점"표시를 통해 이미지 갯수 및 넘어가는 표시를 한다. 

 

구현 방법

1. 먼저 CollectionView를 생성한다. 

private lazy var randomPlaceCollectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .horizontal
    layout.minimumLineSpacing = 0
    layout.minimumInteritemSpacing = 0

    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    collectionView.isPagingEnabled = true
    collectionView.showsHorizontalScrollIndicator = false
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.register(RandomImageCell.self, forCellWithReuseIdentifier: RandomImageCell.identifier)
    collectionView.layer.cornerRadius = 10
    collectionView.layer.masksToBounds = true
    return collectionView
}()

 

  • UICollectionViewFlowLayout() 을 통해 컬렉션 뷰 내부의 아이템의 위치 및 방향에 대해 설정을 한다. 
  • 아래 코드는 내부 아이템의 간격을 0으로 한다는 의미이다. 
// 아이템의 세로 방향
layout.minimumLineSpacing = 0

// 아이템의 가로 방향
layout.minimumInteritemSpacing = 0

 

  • isPagingEnabled를 true로 설정하여, 사용자가 스크롤할 때 한 페이지씩 스크롤되도록 한다.
// isPagingEnabled를 true로 설정하여, 사용자가 스크롤할 때 한 페이지씩 스크롤되도록 한다.
collectionView.isPagingEnabled = true

// 수평 스크롤 인디케이터(스크롤 바)를 보이지 않게 설정한다.
collectionView.showsHorizontalScrollIndicator = false

 

 

2. UIPageControl를 생성한다. 

private lazy var pageControl: UIPageControl = {
    let pageControl = UIPageControl()
    pageControl.currentPage = 0
    pageControl.translatesAutoresizingMaskIntoConstraints = false
    return pageControl
}()
  • UIPageControl은 페이지 기반 네비게이션을 표시하는 컨트롤로, 일반적으로 여러 페이지를 나타내는 작은 점을 표시한다.

 

3. 이미지를 담는 배열을 생성한다. 

var randomImages: [UIImage] = []

 

 

4. Delegate를 선언, PageControl 업데이트 한다. 

randomPlaceCollectionView.delegate = self
randomPlaceCollectionView.dataSource = self

// PageControl 업데이트
pageControl.numberOfPages = randomImages.count

 

 

5. RandomImageCell 파일 생성한다.

import UIKit

class RandomImageCell: UICollectionViewCell {
    
    static let identifier = "RandomImageCell"
    
    var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.backgroundColor = .systemYellow
        imageView.clipsToBounds = true
        imageView.contentMode = .scaleAspectFill
        imageView.layer.cornerRadius = 10
        
        //imageView.layer.masksToBounds = true
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
            contentView.addSubview(imageView)
        configureConstraints()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func configureConstraints() {
        
        let imageViewConstraints = [
            imageView.topAnchor.constraint(equalTo: contentView.topAnchor),
            imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ]
        
        NSLayoutConstraint.activate(imageViewConstraints)
    }
}

 

 

6. Delegate 선언에 따른 Extension 구현한다.

extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return randomImages.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RandomImageCell.identifier, for: indexPath) as? RandomImageCell else { return UICollectionViewCell() }
        
        cell.imageView.image = randomImages[indexPath.item]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 300)
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let width = scrollView.frame.width
        let currentPage = Int((scrollView.contentOffset.x + width / 2) / width)
        pageControl.currentPage = currentPage
    }
}

 

 

  • 아래 메서드는 섹션 내의 항목 수를 반환한다. 
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return randomImages.count
}

 

  • 주어진 인덱스 경로에 대한 셀을 반환한다.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RandomImageCell.identifier, for: indexPath) as? RandomImageCell else { return UICollectionViewCell() }
    
    cell.imageView.image = randomImages[indexPath.item]
    return cell
}

 

  • 각 항목의 크기를 반환한다.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: collectionView.frame.width, height: 300)
}

 

  • 스크롤 뷰가 스크롤될 때 호출된다.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let width = scrollView.frame.width
    let currentPage = Int((scrollView.contentOffset.x + width / 2) / width)
    pageControl.currentPage = currentPage
}

 

 

  • 스크롤 뷰가 스크롤될 때 현재 페이지를 계산하여 pageControl의 currentPage 속성을 업데이트한다.
  • scrollView.contentOffset.x는 스크롤 뷰의 현재 수평 스크롤 위치를 나타낸다.
  • scrollView.frame.width를 이용해 현재 페이지를 계산한다.

 

7. 컬렉션뷰, pageControl 제약 조건 선언