iOS/UIKit
[UIkit] 이미지 사이즈에 따른 동적 컬렉션뷰 셀
늘스토리 주인장
2025. 2. 3. 18:35
728x90
반응형
🧸 시작
컬렉션뷰셀이 이미지 사이즈에 따라 셀의 사이즈도 바뀐다!
🧸 폴더로 이동한다.
import UIKit
import DesignSystem
class CustomCollectionViewController: UIViewController, UICollectionViewDelegate {
var collectionView: UICollectionView!
var imageList: [UIImage] = []
override func viewDidLoad() {
super.viewDidLoad()
// 이미지 목록 초기화
imageList = [
DesignSystemDemoAppAsset.shirt.image,
DesignSystemDemoAppAsset.blueshirt.image,
DesignSystemDemoAppAsset.nike.image,
DesignSystemDemoAppAsset.nike2.image,
DesignSystemDemoAppAsset.nike3.image,
DesignSystemDemoAppAsset.onepiece.image,
DesignSystemDemoAppAsset.pants.image,
DesignSystemDemoAppAsset.pants2.image,
DesignSystemDemoAppAsset.white.image
]
let layout = CollectionViewLayout()
layout.delegate = self
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.backgroundColor = .white
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
view.addSubview(collectionView)
}
}
extension CustomCollectionViewController: CollectionViewLayoutDelegate {
// 이미지 사이즈에 따른 셀 높이 계산
func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {
let cellWidth: CGFloat = (view.bounds.width - 4) / 2
let imageHeight = imageList[indexPath.item].size.height
let imageWidth = imageList[indexPath.item].size.width
let imageRatio = imageHeight / imageWidth
return imageRatio * cellWidth
}
}
extension CustomCollectionViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageList.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let imageView = UIImageView(image: imageList[indexPath.item])
imageView.frame = cell.bounds
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
cell.contentView.addSubview(imageView)
return cell
}
}
public protocol CollectionViewLayoutDelegate: AnyObject {
func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat
}
public class CollectionViewLayout: UICollectionViewFlowLayout {
public weak var delegate: CollectionViewLayoutDelegate?
private var contentHeight: CGFloat = 0
private var contentWidth: CGFloat {
guard let collectionView = collectionView else {
return 0
}
let insets = collectionView.contentInset
return collectionView.bounds.width - (insets.left + insets.right)
}
// 전체 콘텐츠 사이즈 계산
public override var collectionViewContentSize: CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
private var cache: [UICollectionViewLayoutAttributes] = []
public override init() {
super.init()
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func prepare() {
guard let collectionView = collectionView, cache.isEmpty else { return }
let numberOfColumns: Int = 2
let cellPadding: CGFloat = 5
let cellWidth: CGFloat = contentWidth / CGFloat(numberOfColumns)
let xOffSet: [CGFloat] = [0, cellWidth]
var yOffSet: [CGFloat] = .init(repeating: 0, count: numberOfColumns)
var column: Int = 0
for item in 0..<collectionView.numberOfItems(inSection: 0) {
let indexPath = IndexPath(item: item, section: 0)
let imageHeight = delegate?.collectionView(collectionView, heightForPhotoAtIndexPath: indexPath) ?? 180
let height = cellPadding * 2 + imageHeight
let frame = CGRect(x: xOffSet[column],
y: yOffSet[column],
width: cellWidth,
height: height)
let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = insetFrame
cache.append(attributes)
contentHeight = max(contentHeight, frame.maxY)
yOffSet[column] = yOffSet[column] + height
column = yOffSet[0] > yOffSet[1] ? 1 : 0
}
}
public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}
public override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.item]
}
}
📂 결과
고정된 사이즈로 나타내는 거보다 다채로운 셀의 사이즈로 신선한 느낌으로 예쁜 거 같다!
728x90
반응형
728x90
반응형