개발하는 동글 :]

[TIL],[UIKit],[Carousel CollectionView 적용] 본문

카테고리 없음

[TIL],[UIKit],[Carousel CollectionView 적용]

동글하다 2023. 9. 25. 21:19

1. 팀 프로젝트의 시작

1.1 팀 프로젝트에서의 역할

위의 이미지의 화면을 담당하기로 하였고 첫 화면은 Carousel CollectionView 를 적용하고 두번 째 modal 페이지는 다양한 animation을 적용해볼 예정이다

1.2 Carousel CollectionView의 적용

전에 연습해 보았던 Carousel CollectionView 를 적용한 모습

1.3 전체 코드

//
//  FeatureViewController.swift
//  oewoboka
//
//  Created by 김도현 on 2023/09/25.
//

import Foundation
import UIKit
import SnapKit

final class FeatureViewController: UIViewController {
    
    private let viewModel = FeatureViewModel()
    
    private let featureCollectionView: UICollectionView = {
        let flowLayout = UICollectionViewFlowLayout()
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
        flowLayout.scrollDirection = .horizontal
        return collectionView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
        setUp()
    }
    
}

private extension FeatureViewController {
    // MARK: - SetUp

    func setUp() {
        view.addSubview(featureCollectionView)
        let cellWidth: CGFloat = floor(viewModel.cellSize.width)
        let insetX = (view.bounds.width - cellWidth) / 2.0
        
        featureCollectionView.contentInset = UIEdgeInsets(top: 0, left: insetX, bottom: 0, right: insetX)
        featureCollectionView.showsHorizontalScrollIndicator = false
        featureCollectionView.decelerationRate = .fast
        featureCollectionView.register(
            FeatureCollectionViewCell.self,
            forCellWithReuseIdentifier: FeatureCollectionViewCell.identifier
        )
        featureCollectionView.delegate = self
        featureCollectionView.dataSource = self
        featureCollectionView.snp.makeConstraints { make in
            make.edges.equalTo(view.safeAreaLayoutGuide)
        }
    }
    
}

private extension FeatureViewController {
    // MARK: - Animation
    func animateZoomforCell(zoomCell: UICollectionViewCell) {
        UIView.animate(
            withDuration: 0.2,
            delay: 0,
            options: .curveEaseOut,
            animations: { zoomCell.transform = CGAffineTransform( scaleX: 1.2, y: 1.2) },
            completion: nil)
    }
    
    func animateZoomforCellremove(zoomCell: UICollectionViewCell) {
        UIView.animate(
            withDuration: 0.2,
            delay: 0,
            options: .curveEaseOut,
            animations: { zoomCell.transform = .identity },
            completion: nil)
        
    }
}

extension FeatureViewController: UICollectionViewDataSource{
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        viewModel.testAry.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = self.featureCollectionView.dequeueReusableCell(withReuseIdentifier: FeatureCollectionViewCell.identifier, for: indexPath) as? FeatureCollectionViewCell else {
            return UICollectionViewCell()
        }
        return cell
    }
}

extension FeatureViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return viewModel.minItemSpacing
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return viewModel.cellSize
    }
    
    // MARK: Paging Effect
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let cellWidthIncludeSpacing = viewModel.cellSize.width + viewModel.minItemSpacing

        var offset = targetContentOffset.pointee
        let index = (offset.x + scrollView.contentInset.left) / cellWidthIncludeSpacing
        let roundedIndex: CGFloat = round(index)
        offset = CGPoint(x: roundedIndex * cellWidthIncludeSpacing - scrollView.contentInset.left, y: scrollView.contentInset.top)
        targetContentOffset.pointee = offset
    }
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
        let cellWidthIncludeSpacing = viewModel.cellSize.width + viewModel.minItemSpacing
        let offsetX = featureCollectionView.contentOffset.x
        let index = (offsetX + featureCollectionView.contentInset.left) / cellWidthIncludeSpacing
        let roundedIndex = round(index)
        let indexPath = IndexPath(item: Int(roundedIndex), section: 0)
        DispatchQueue.main.async { [weak self] in
            guard let self = self else {return}
            guard let cell = featureCollectionView.cellForItem(at: indexPath) else { print("fail");return }
            animateZoomforCell(zoomCell: cell)
        }
        if Int(roundedIndex) != viewModel.previousIndex {
            let preIndexPath = IndexPath(item: viewModel.previousIndex, section: 0)
            if let preCell = featureCollectionView.cellForItem(at: preIndexPath) {
                animateZoomforCellremove(zoomCell: preCell)
            }
            viewModel.previousIndex = indexPath.item
        }
    }
}

 

 

2. TIL

2.1 오늘의 회고

1. 팀 프로젝트 과제의 와이어 프레임 회의 진행
2. 팀 프로젝트의 Carousel CollectionView의 프레임을 구현

2.2 내일의 목표

1. 팀 프로젝트 담당 부분 구현

2. Protocel 및 Generics 공부 시간나면 계속해보기!