본문 바로가기

iOS/Swift

zoomable image pager with UICollectionView (swift)

안드로이드의 이미지 뷰페이저와 같이  가로 스크롤 및 확대 가능한 이미지 뷰 페이지 만들기

zoomable image pager with horizontal UICollection like Image ViewPager at Android

 

Test Device
1. iPhone Xs (ios 15.1)
2. iPhone8 (ios 13.7)

 

구현목표

1. 가로 스크롤 되는 페이저 구현

2. 화면에 이미지 하나가 가득차게 표기

3. 이미지 확대 기능

4. 이미지 개수 만큼 indicator 표기

 

구성요소 

Component

UIViewController

- UICollectionView

-- UICollectionViewCell

--- ScrollVIew

---- ImageView

- UIPageControl

 

 

스토리보드 설정

StoryBoard Setting

더보기

 

 

FullScreenPagerViewController 구조

FullScreenPagerViewController

collectionView: UICollectionView 
collectionView: UICollectionView 

fullScreenPagerCell: UICollectionViewCell 
fullScreenPagerCell: UICollectionViewCell 

scrollView: UIScrollView
scrollView: UIScrollView

ugImageView: UIImageView
ugImageView: UIImageView

imgPageControl: UIPageControl
imgPageControl: UIPageControl

 

 


전체 코드

Full Code

FullScreenPagerViewController 라는 이름의 파일 하나에 작성.

import UIKit
import Nuke //AWS의 이미지 경로로 이미지 표기하기 위해 사용//이미지 파일로 불러올 경우 안써도 됨


class FullScreenPagerViewController: UIViewController {
	//이전화면에서 넘겨받은 이미지 구조 배열
    //이미지 경로 또는 이미지 배열로 변경 가능
    var items: [UsedGoodsDetailItem.ImageStruct]? 
    
    //처음에 몇번째 이미지가 보일지 이전 화면에서 넘겨 받는 이미지 순서
    var current: Int?
    
    @IBOutlet weak var imgPageControl: UIPageControl!
    
    @IBOutlet weak var collectionView: UICollectionView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        
        //cell을 collectionView 크기만큼 키움
        let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = CGSize(width: self.view.frame.width, height: self.view.frame.height)
        
        //pagecontrol 설정
        imgPageControl.pageIndicatorTintColor = UIColor.lightGray
        imgPageControl.currentPageIndicatorTintColor = UIColor.red
        imgPageControl.hidesForSinglePage = true
        imgPageControl.numberOfPages = items?.count ?? 0
        imgPageControl.currentPage = current ?? 0
        
    }
    
    //UIPageControl의 값이 바뀔때 CollectionView의 cell을 넘기기 위한 Action
    @IBAction func pageChanged(_ sender: UIPageControl) {
        print("page changed : \(imgPageControl.currentPage)")
        let indexPath = IndexPath(item: imgPageControl.currentPage, section: 0)
        self.collectionView.isPagingEnabled = false
        self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
        self.collectionView.isPagingEnabled = true
    }
    
    //UICollectionView의 스크롤을 넘겨 다음 페이지의 이미지로 전환했는지 확인 //Paging 확인
    //UIPageControl 값 변경
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        self.imgPageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
    }

}
extension FullScreenPagerViewController: UICollectionViewDelegate, UICollectionViewDataSource {
  	//collectionView의 cell 개수 == collectionView에 표기할 이미지 개수
  	func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items?.count ?? 0
    }
    
    //collectionView를 스크롤 할 경우 paing완료 되면 pageControl에 현재 페이지 표기
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let page = Int(targetContentOffset.pointee.x / self.collectionView.frame.width)
            self.imgPageControl.currentPage = page
    }
    
    //collectionViewCell 선언 및 cell의 imageview에 이미지 지정
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "fullScreenPagerCell", for: indexPath) as?
                FullScreenPagerCell else {
               return UICollectionViewCell()
           }
        
        let options = ImageLoadingOptions(
            failureImage: UIImage(systemName: "icloud.slash.fill")
        )


        let imageRequest = ImageRequest(url: URL(string: "image url"))!
                                        , processors: [ImageProcessor.Resize(size: cell.ugImageView.frame.size)]
                                            , priority: .high
                                            , options: ImageRequestOptions.init())

            Nuke.loadImage(with: imageRequest
                           , options: options
                           , into: cell.ugImageView                       , progress: nil
                           , completion: nil)
        return cell
                
    }
    
}
//UICollection의 cell class
class FullScreenPagerCell: UICollectionViewCell, UIScrollViewDelegate {
    var hashed: String?
    
    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var ugImageView: UIImageView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        //이미지 확대 배수 설정// 1~3배 확대 가능
        self.scrollView.minimumZoomScale = 1.0
        self.scrollView.maximumZoomScale = 3.0
        self.scrollView.delegate = self
    }
    
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return ugImageView
    }
    
 
}