์ง๊ธ ๊ตฌํํด์ผํ๋ ๋ทฐ
์ด๋ ๊ฒ ์ปฌ๋ ์ ๋ทฐ๋ฅผ ๋์์ผํ๋ค. ๋ด๊ฐ ์ด์ ์ ์ง๋จ๋ ์ฝ๋๊ฐ ์์ด์ ๊ทธ ์ฝ๋๋ฅผ ์ด์ฉํ ๊ฒ์ด๋ค.
์ปฌ๋ ์ ๋ทฐ๋ฅผ ๋์ ๋ค. ๊ทผ๋ฐ ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค.
์ด๋ ๊ฒ ๋น๊ณต๊ฐ์ด ์ค์์ ์๊ธฐ๋ ๊ฒ์ด๋ค! ๊ธฐ๋ณธ์ ์ผ๋ก ์ปฌ๋ ์ ๋ทฐ๋ ์์ชฝ ๋ ์ด์์์ ๋ง์ถ๋๋ก ์ ๋ ฌ์ด ๋๋ ๊ฒ ๊ฐ๋ค. ๊ทธ๋์ ์ผ์ชฝ์ผ๋ก ์ ๋ ฌํ๋ ์ฝ๋๋ฅผ ๋ฐ๋ก ์ปค์คํ ํด์ฃผ์ด์ผํ๋ค๊ณ ํ๋ค.
๋์ ํด๋ณด์!
layoutAttributesForElements()
์ธํฐ๋ท์ ๋ง์ ๋ ํผ๋ฐ์ค๊ฐ ์์๊ณ , ๊ทธ ์ค ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ๊ฐ์๋ค.
https://velog.io/@yoonah-dev/CollectionView-Left%EC%A0%95%EB%A0%AC
class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes }
var leftMargin: CGFloat = 0.0
var maxY: CGFloat = -1.0
attributes?.forEach { layoutAttribute in
guard layoutAttribute.representedElementCategory == .cell else {
return
}
if layoutAttribute.frame.origin.y >= maxY {
leftMargin = 0.0
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
maxY = max(layoutAttribute.frame.maxY , maxY)
}
return attributes
}
}
์ด๋ ๊ฒ ๊ตฌํํ๋ ๊ฒ ๊ฐ์๋ค. ์ผ๋จ ์๋ฆฌ๋ฅผ ์์์ผ ๋ด ์ฝ๋์ ์ ์ฉ์ํฌ ์ ์์ผ๋๊น ํ๋ํ๋ ๋ฏ์ด๋ณด์.
ํด๋น ์ฝ๋์ ๋ํด์ ๊ฐ๋ตํ ์ค๋ช ํ์๋ฉด,
์ปค์คํ ํด์ ๋ง๋ ํด๋น ํด๋์ค์์๋, UICollectionViewLayoutAttributes๋ฅผ ์ด์ฉํด์ ์ปฌ๋ ์ ๋ทฐ์ ๋ชจ์์ ์กฐ์ ํ๋ ค๊ณ ํฉ๋๋ค.
- attributes: ์ฌ๊ธฐ์๋ ํ์ฌ ๊ฐ๊ฐ์ ์
๋ด๋ถ์ ์๋ ์์ฑ๋ค์ ์ ๋ถ map ํด์ array ํํ๋ก ๋ฃ์ด๋ ๋ฐฐ์ด์
๋๋ค.
- layoutAttributesForElements : ํด๋น ์ธ์คํด์ค๊ฐ, ๊ฐ๊ฐ์ cell ๋ด๋ถ์ ์๋ ๋ชจ๋ ๋ ์ด์์์ ๋ํ ์์ฑ์ ๊ฒ์ํด์ฃผ๊ณ , attributes์ ๋ด์ต๋๋ค.
- leftMargin: ์ผ์ชฝ ์ ๋ ฌ์ ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ๊ฐ์ฅ ์ผ์ชฝ์ ์ผ๋งํผ ๋จ๊ธฐ๊ณ ์ผ์ชฝ์ผ๋ก ๋ถ์ผ์ง ๊ฒฐ์ ํ๋ ์๋ฅผ CGFloat ํํ๋ก ๋ฐ์ต๋๋ค.
- representedElementCategory: ์ด๋ค ๋ฒ์ฃผ์ ์ํ๋์ง ์นดํ ๊ณ ๋ฆฌ๋ก ๋ํ๋ด์ค๋๋ค. ์ฆ, ์ด ์์ฑ์ ๊ฐ์ ์ฌ์ฉํ์ฌ ๋ ์ด์์ ์์ฑ์ด ์ , ๋ณด์กฐ ๋ณด๊ธฐ ๋๋ ์ฅ์ ๋ณด๊ธฐ๋ฅผ ์ํ ๊ฒ์ธ์ง ๊ตฌ๋ณํ ์ ์์ต๋๋ค.
์ ์์ฑ๋ค์ ๋น๊ตํด์, ํ์ฌ cell์ ์์ฑ์ frame์ด maxY ๋ณด๋ค ํฌ๋ค๋ฉด, ์ผ์ชฝ์ ๋ ฌ์ด ๋์ง ์์๋ค๊ณ ํ๋จํ์ฌ ์๊น ์ค์ ํ leftMargin๊ฐ๋ง ๋จ๊ฒจ๋๊ณ ์ผ์ชฝ์ผ๋ก ๋ถ์ฌ๋ฒ๋ฆฌ๋ ํจ์์ ๋๋ค.
์ด๋ ๊ฒ cell์๋ํ ์์ฑ์ ์ค์ ํด๋ layout์, CollectionView์ ๊ทธ๋๋ก ์ ์ฉํด์ฃผ๋ฉด, ์ผ์ชฝ์ ๋ ฌ์ด ๋๋ ์์ฑ์ ๊ฐ์ง cell์ layout์ผ๋ก ๊ฐ๊ฒ๋์ด, ์ผ์ชฝ์ ๋ ฌ์ด ๊ฐ๋ฅํด์ง๋๋ค.
์ด ์ฝ๋ ๋ฃ๊ณ , flowlayout ๋ฃ๋ ๋ถ๋ถ์ ํด๋น ํด๋์ค๋ฅผ ๋ฃ์ด์ฃผ๋๊น ๋ฐ๋ก ์๋ฃ๋์๋ค.
private lazy var collectionView: UICollectionView = {
let layout = **LeftAlignCollectionViewFlowLayout**()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
layout.scrollDirection = .vertical
layout.minimumLineSpacing = Size.cellInterval
layout.minimumInteritemSpacing = Size.cellInterval
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(MyNewsDrawerCollectionViewCell.self, forCellWithReuseIdentifier: MyNewsDrawerCollectionViewCell.className)
return collectionView
}()
์ฝ๋์์ leftMargin์ ์ ์ธํ๊ณ ์์ผ๋ก ์ญ ๋ถ์ด๊ฒ ๋ค๋ ๋ป์ด๋ค. ๋๋ ์ผ์ชฝ์ ์์ ํ 0์ผ๋ก ๋ถ์ฌ์ผํ๊ธฐ ๋๋ฌธ์ leftMargin์ 0์ผ๋ก ๋ฐ๊ฟ์ฃผ์๋ค.
delegateFlowLayout ์ด๋ ๊ทธ๋ฅ FlowLayout์ด๋ ์ฐจ์ด์ ?
๐ฃ UICollectionViewFlowLayout
- ์๋ ์ฒ๋ผ, ์ฃผ๋ก ์ด๊ธฐ๊ฐ์ ์ค์ ํ๋ ๊ฒฝ์ฐ์ ํด๋น ๊ฐ์ฒด๋ฅผ ์์ฃผ ์ฌ์ฉํ๋ค. delegate ๋ณด๋ค ํจ์ฌ ๊ฐ๋จํ๊ธฐ ๋๋ฌธ์ด๋ค.
var homeCollectionView: UICollectionView = {
let layout = **UICollectionViewFlowLayout**()
**layout.scrollDirection = .vertical
layout.minimumLineSpacing = 36
layout.sectionInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
layout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width - 20*2, height: 200)**
let collectionView = UICollectionView(frame: .zero,
collectionViewLayout: layout)
return collectionView
}()
์์์ฒ๋ผ ์ด๊ธฐ ๊ฐ์ ์ค์ ํ๋๋ฐ ์ฌ์ฉ ๊ฐ๋ฅํ์ง๋ง, ์๋์ฒ๋ผ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ์ปค์คํ ํด์ค ๋ค, ๊ทธ ๋ ์ด์์์ ์์๋ฐ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
class **StretchHeaderLayout**: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
... ์๋ต
return layoutAttributes
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
class ViewController: UIViewController {
@IBOutlet weak var stickyCollectionView: UICollectionView!
let stickyFlowLayout = **StretchHeaderLayout**()
override func viewDidLoad() {
super.viewDidLoad()
}
}
๋์ ๋ฐฉ์
์๋ ๊ทธ๋ฆผ์ CollectionView์ UICollectionViewFlowLayout ๊ฐ์ฒด๊ฐ ์ํธ์์ฉํ๋ ๋ฐฉ์์ด๋ค.
๊ทธ๋ฆผ์ ์ฒ์ ๋ณด๋ฉด, CollectionView๊ฐ prepareLayout์ ํตํด์ ๋ ์ด์์์ ์ด๊ธฐ๊ฐ์ ์ค์ ํ๊ณ , ์ดํ CollectionView์ ํฌ๊ธฐ๋ฅผ ๋ฐ๊ณ , Cell์ ํฌ๊ธฐ๋ค์ ์ง์ ํ๊ณ ๋ฐ๋ ์์๋๋ก ์ด๋ฃจ์ด์ง๋ค! ์ฌ๋ ๐๐ป
๋์ํ๋ ๋ฉ์๋์ ๋ํด์ ๊ฐ๋จํ๊ฒ ์์๋ณด์๊ตฟ
- prepare(): ์ด๊ธฐ์ collectionView์ ๋ ์ด์์์ ์ค์ ํ ๋ ํธ์ถ๋ฉ๋๋ค. ์ฆ, ์ฌ์ด์ฆ๋ฅผ ์ํ ์ด๋ค ์ ํ ์ด ํ์ํ ๋, ์ด ๋ฉ์๋๋ฅผ override ํด์ ์ฌ์ฉํ ์ ์๋ค. (CollectionView์ ์ด๊ธฐ์ค์ ์ด ์๋ ๋ ์ด์์ ์ฐ์ฐ์ด ์ผ์ด๋๊ธฐ ์ ์ด๋ค.)
- layoutAttributesForElements(rectr: ) -> [UICollectionViewLayoutAttributes]? : CollectionView์์ ์๋ ๋ชจ๋ ์์์ ๋ํ Layout์์๋ค์ ๋ฆฌํดํ๋ค. (ํ์ฌ ํ๋ฉด์ ๋ณด์ด๋ ์์)
- layoutAttributesForItem(indexPath: ) -> UICollectionViewLayoutAttributes?: CollectionView์ ์๊ตฌํ IndexPath์ Layout์์๋ค์ ๋ฆฌํดํ๋ค.
- shouldInvalidateLayout(newBounds: ) -> Bool : Bounds์ ๋ณํ๊ฐ ์์ ๋๋ง๋ค, ํจ์๋ฅผ ํธ์ถํ ์ง ๊ฒฐ์ ํ๋ค.
๐ฃ UICollectionViewDelegateFlowLayout
- ๋ทฐ ์ปจํธ๋กค๋ฌ์์ ํด๋น ํ๋กํ ์ฝ์ ์ฑํํด์ ๋ฐ์ดํฐ์ ๋ง๊ฒ collectionView์ ๋ ์ด์์์ ์ปค์คํ ํ๋ค.
- ๋ฐ์ดํฐ์ ๋ง๊ฒ ์ปค์คํ ํค์ ํํ ๊ฒฝ์ฐ์ ์ข๋ค.
- delegate ๋์ ์จ์ฃผ๋ฉด ๋๋ค..?
์ฐธ๊ณ ์๋ฃ: https://dongminyoon.tistory.com/29