์ ๋ง ์์ฃผ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ ์ค ํ๋์ธ ์ปฌ๋ ์ ๋ทฐ ํ์ด์ง! UICollectionView ์์ฑ์ isPagingEnable์ด ์์ง๋ง
์ด๋ ๊ฒ ์ ๊ณผ ์ ์ฌ์ด์ minimumLineSpacing์ด ๋ค์ด๊ฐ๊ฑฐ๋ sectionInset์ด ๋ค์ด๊ฐ๋ฉด ํ์ด์ง์ด ์ ๋๋ก ๋์ง ์์ต๋๋ค ๐ฅฒ
scrollViewDidScroll์์ ๋ก๊ทธ๋ฅผ ์ฐ์ด๋ณด๋ฉด ๊ทธ ์ด์ ๋ฅผ ์ ์ ์๋๋ฐ์
UIScreen์ ๋์ด๊ฐ 390์ด๊ณ ํ๋ฒ ํ์ด์ง์ด ๋ ๋ ํ๋ฉด ๋์ด ๋งํผ ํ์ด์ง์ด ๋๋ ๊ฒ์ ์ ์ ์์ด์
์ ์ฌ์ด์ฆ๋ 320์ผ๋ก ํ๋ฉด ๋์ด๋ณด๋ค ์๊ณ minimumLineSpacing์ 7๋ก ์ค์ ํด ์คฌ๊ธฐ ๋๋ฌธ์ ํ๋ฒ์ ํ๋ฉด ๋์ด ๋งํผ ํ์ด์ง ํ๋ฉด
ํ์ด์ง๊ฒ ๋ฉ๋๋ค!
์ข์ฐ ์ฌ๋ฐฑ ํฌํจ, ์ ์ฌ์ด spacing ๊น์ง ํฌํจํด์ ํ์ด์ง์ด ๋๊ฒ ํ๋ UI ๊ฐ ๋ง์ด ์ฌ์ฉ๋๋๋ฐ ์ด ์ฐธ์ ์ ๋ฆฌํด ๋ด ์๋น
scrollViewWillEndDragging
optional func scrollViewWillEndDragging(_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>)
์ฐ์ ์ฌ์ฉํด ์ค ํจ์๋ scrollViewWillEndDragging!
UIScrollViewDelegate์์ ์ ๊ณตํ๋ ํจ์์ ๋๋ค. UICollectionView๊ฐ UIScrollView๋ฅผ ์์ ๋ฐ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํด ์ค ์ ์์ด์!
์ฌ์ฉ์๊ฐ UIScrollView์ ์ปจํ ์ธ ๋ฅผ ์คํฌ๋กค๋งํ๋ค๊ฐ ๋ฉ์ถ๊ฒฝ์ฐ ๋ธ๋ฆฌ๊ฒ์ดํธ์๊ฒ ์ด๋ฅผ ์๋ฆฝ๋๋ค
์ด๋ velocity๋ ํฐ์น๊ฐ ๋๋ ์์ ์ ์คํฌ๋กค ๋ทฐ์ ์๋์ด๊ณ targetContentOffset์ ์คํฌ๋กค๋ง ์ก์ ์ด ์๋๋ฅผ ์ค์ด๋ค๊ฐ ๋ฉ์ถ๋ ์ง์ ์ ์์ ์คํ์ ์ ๋๋ค.
์ ์ ์ ์คํฌ๋กค ์ก์ ์ด ๋๋ ๋ ์์ ์ปจํ ์ธ ์คํ์ ์ ๋ณ๊ฒฝํด ์ฃผ๋ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํด ์ค ์ ์์ต๋๋ค
์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ์ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์ด์ ๐๐ป ๋งํฌ
class CarouselEffectViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
let cellWidth = UIScreen.main.bounds.width - 70
let cellHeight = UIScreen.main.bounds.height - 100
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: cellWidth, height: cellHeight)
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 7
collectionView.contentInset = UIEdgeInsets(top: 0, left: 34, bottom: 0, right: 34)
collectionView.collectionViewLayout = layout
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UINib(nibName: "CaraouselCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CaraouselCollectionViewCell")
}
}
}
extension CarouselEffectViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CaraouselCollectionViewCell", for: indexPath) as? CaraouselCollectionViewCell
cell?.idx = "\(indexPath.item)"
return cell ?? UICollectionViewCell()
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
}
}
๊ธฐ๋ณธ UI์ collectionView, UICollectionViewFlowLayout์ ๋ํ ์ค์ ์ ํด์ค ๋ค ์์์ ์์ ๋ณธ ํจ์๋ฅผ ์ถ๊ฐํด ์ค๋๋ค
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
return
}
let cellWidth = layout.itemSize.width
let cellSpacing = layout.minimumLineSpacing
let contentLeftInset = scrollView.contentInset.left
let cellWithSpacing = cellWidth + cellSpacing
let offsetX = targetContentOffset.pointee.x
let index = (offsetX + contentLeftInset) / cellWithSpacing
let roundedIndex: CGFloat = round(index)
let adjustedOffsetX = roundedIndex * cellWithSpacing - scrollView.contentInset.left
targetContentOffset.pointee = CGPoint(x: adjustedOffsetX, y: scrollView.contentInset.top)
}
์์๋ณด๊ธฐ ์ฝ๊ฒ ํ๋ ค๊ณ ์๊ฒ ์ชผ๊ฐ์ ๋ณ์๋ฅผ ์์ฑํด ์ฃผ์๋๋ฐ ์ง์ ๋์ ํ์ ๋ ๋ฉ๋๋น๐ฆ
์ฌ๊ธฐ ๊น์ง ํ๋ฉด ์ํ๋๋๋ก spacing๊ณผ inset์ ํฌํจํ๊ณ ์ ์ด ๊ฐ์ด๋ฐ๋ก ์ค๋ฉด์ ํ์ด์ง์ด ๋ฉ๋๋ค!!
์ง๊ธ ์ํ์์ ์คํฌ๋กค ํ๋ฉด ๊ต์ฅํ ์ค๋ฅด๋ฅต ๋์ด๊ฐ๋ ๋๋์ด ๋ค ์ ์๋๋ฐ ํํ ๋์ด๊ฐ๋ ํ์ด์ง์ ์ํ๋ฉด
collectionView.decelerationRate = .fast
์ ์ถ๊ฐํด ์ค๋๋ค. ์ฌ์ฉ์๊ฐ ์คํฌ๋กค ํ ์๊ฐ๋ฝ์ ๋๋ ๊ฐ์ํ๋ ์๋์ธ๋ฐ ์ด ๊ฐ์ ์๋๋ฅผ ๋น ๋ฅด๊ฒ ๋ณ๊ฒฝํ๋ฉด ํฑํฑ ๋์ด๊ฐ๋๋ค
์ด์ ์ฝ๋๋ฅผ ์ดํดํด ๋ด ์๋น ๐
guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
return
}
์ฐ์ collectionView์์ ์ง์ ํด ์ค UICollectionViewFlowLayout์ ์ ๊ทผํด์ ์ด layout ์ ๋ณด๋ฅผ ์ฌ์ฉํ ์๊ฐ ์์ด์!
let cellWidth = layout.itemSize.width
let cellSpacing = layout.minimumLineSpacing
let contentLeftInset = scrollView.contentInset.left
์ด๋ ๊ฒ ์์ฑ๋ค์ ์ฌ์ฉํ ์ ์์ด์ ๊ตณ์ด ์ ์ ํฌ๊ธฐ๋ spacing์ ๋ฐ๋ก ์ ์ญ์ผ๋ก ์ ์ธํด ์ฃผ์ง ์์๋ ๋์!
์ฌ๊ธฐ์ ์๊ณ ๋์ด ๊ฐ๋ฉด ์ข์๊ฒ contentLeftInset์ผ๋ก ์ ์ธํ scrollView์ contentInset์ ๋๋ค
์ด ๊ฐ์ด ์๋ฏธํ๋ ๊ฑด ๋ง ๊ทธ๋๋ก ์คํฌ๋กค ๋ทฐ์ ์ธ์ ์ธ๋ฐ์ ์ด๊ฒ ์ ํ์ํ์ง ์์๋ด ์๋ค!
collectionView.contentInset = UIEdgeInsets(top: 0, left: 34, bottom: 0, right: 34)
์ฐ์ ์์์ ์ค์ ํด ์ค ๊ฐ์ ์ด๋ ์ต๋๋ค! collectionView์ contentInset ์์ฒด๋ฅผ 34๋ก ์ค์ ํด ์ฃผ๋ฉด ์คํฌ๋กค ๋ทฐ๊ฐ 34 ๋งํผ ๋ฐ๋ฆฝ๋๋ค!
scrollViewWillEndDragging์์ contentLeftInset ์ ์ธ ์๋ ๋ถ๋ถ์ ๋ชจ๋ ์ฃผ์ ์ฒ๋ฆฌํ๊ณ scrollViewDidScroll์์ ๋ก๊ทธ๋ฅผ ์ฐ์ด๋ณด๊ฒ ์ต๋๋น
์คํฌ๋กค์ด ๋๋ ํ ๋ง์ง๋ง์ -34์์ ๋ฉ์ถ ๊ฒ์ ํ์ธ ํ ์ ์์ด์! scrollView.contentInset.left ๋ํ ๋์ผํ๊ฒ ์ง์ ํด ์ค ๋๋ก 34 ๊ฐ์ ๊ฐ์ง๋๋ค
collectionView.contentInset = UIEdgeInsets(top: 0, left: 34, bottom: 0, right: 34)
์ด ์ฝ๋๋ฅผ ์ฃผ์ ์ฒ๋ฆฌ ํ๊ณ
layout.sectionInset = UIEdgeInsets(top: 0, left: 34, bottom: 0, right: 34)
์ด๋ฒ์๋ UICollectionViewFlowLayout์ sectionInset ์์ฑ์ ์ค์ ํด ์ค๋๋ค! ์ด๋ ๊ฒ ํด๋ ์ปฌ๋ ์ ๋ทฐ์๋ ๋๊ฐ์ด ์ธ์ ์ด ๋ค์ด๊ฐ์ง๋ง ๋ค๋ฅธ ์ ์ด ์์ด์!
layout์ sectionInset์ ์ค์ ํด ์ฃผ๋ ๊ฒฝ์ฐ ์คํฌ๋กค ๋ทฐ์ ์ปจํ ํธ ์คํ์ ์ ๋ณ๊ฒฝ๋์ง ์์์
๋ค์ ์ฝ๋๋ก ๋์์์
let cellWithSpacing = cellWidth + cellSpacing
let offsetX = targetContentOffset.pointee.x
let index = (offsetX + contentLeftInset) / cellWithSpacing
let roundedIndex: CGFloat = round(index)
์ด ๋ถ๋ถ์ ๋ด ์๋น!
collectionView.contentInset = UIEdgeInsets(top: 0, left: 34, bottom: 0, right: 34)
๋ก ์ค์ ํด ์ค ๊ฒฝ์ฐ์ scrollView.contetnSize.width๋ inset์ ์ ์ธํ๊ณ (์ ๋์ด * ์ ๊ฐฏ์) + (๋ง์ง ๊ฐฏ์ * (์ ๊ฐฏ์ - 1)) ์ ๋๋ค
์คํฌ๋กค ๋ทฐ๊ฐ ์ฒ์์ ๊ฐ์ฅ ์ผ์ชฝ ๋์ ์ด์ ์ด ์๊ณ ์ค๋ฅธ์ชฝ ๋ฐฉํฅ์ผ๋ก ์คํฌ๋กค ํ๋ฉด ๋ฐ์ด์ฑ์ด ๋๋๊ณ ์ต์ข ์ ์ผ๋ก ๊ฐ๊ณ ์ ํ๋ offset์ ์ค์ ํด ๋ ์ธ์ -34์ผ๊ฑฐ์์! ์ด๋ contentLeftInset์ ๊ฐ 34๋ฅผ ๋ํด์ฃผ๋ฉด ์ฒ์ ์ ์ ์์ญ์ 0, ๊ทธ ๋ค์ ์ ์ ์์ญ์ 0 + (์ ๋์ด + spacing) ๋ถํฐ ์์ํ๊ฒ ์ฃ !
let adjustedOffsetX = roundedIndex * cellWithSpacing - contentLeftInset
์ดํ ์ธ๋ฑ์ค์ (์ ๋์ด + spacing) ์ ๊ณฑํด์ ์ค์ offset์ ๊ตฌํ ๋ค ์๋ ๋๋ก contentIset์ left ๊ฐ ๋งํผ ๋ฐ์ด ์ค๋๋ค. (contentSize๋ inset์ ์ ์ธํ ๊ฐ์ด์ง๋ง offset์ inset์ด ์ ์ฉ๋ ๊ฐ์ด๋ฏ๋ก) ๋ง์ฝ inset ์ ๋นผ์ฃผ์ง ์๋๋ค๋ฉด?
์คํฌ๋กค ํ scrollViewWillEndDragging ์ด ํ๋ฉด์ ์ฒซ ๋ฒ์งธ ์ ๋ถํฐ inset -34 ๊ฐ ์ ์ฉ๋์ง ์์ contentOffset์ด 0์ด ๋๋ฉด์ ์ธ์ ์ด ์ ์์ ์ผ๋ก ์กํ์ง ์์ต๋๋ค
๊ทธ ๋ค์ ์ ๋ ๋ง์ฐฌ๊ฐ์ง
์ด ๋ฐฉ๋ฒ์๋ ๋ฌธ์ ์ ์ด ํ๋ ์๋๋ฐ์ฉ ๐ฆ
๊น์ง ๊น์ง ์กฐ๊ธ์ฉ ์คํฌ๋กค๋ง ํ์ ๋ ์ด๋ ๊ฒ ์ฟฐ์ฒ์ฟฐ์ฒ ๋๋ ๋ฌธ์ ์ ์ด ์์ต๋๋ซ ์๋ ๊ฐ๋ ค๋ targetOffset๊ณผ ๊ณ์ฐ๋ offset ์ฌ์ด์์ ๋ฐ์ํ๋ ๋ฌธ์ ๊ฐ์๋ฐ ์ด๊ฒ๋ ์กฐ๋ง๊ฐ ์์ ํด์ ๊ธ์ ์จ๋ณด๊ฒ ์ต๋๋ค
โญ๏ธ ์ด์ํ ์ ์ด๋ ๋ฌธ์ ์ ์ด ์๋ค๋ฉด ๋๊ธ๋ก ๊ณต์ ๋ถํ๋๋ ค์!!!
์ฐธ๊ณ ์ฌ์ดํธ
'๐ iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift/CoreAnimation] CABasicAnimation ์ด๋ (0) | 2022.06.02 |
---|---|
[iOS/Swift] UICollectionView paging ๋์ปฅ ๊ฑฐ๋ฆฌ๋ ์ด์ ์์ ํ๊ธฐ (0) | 2022.06.01 |
[Swift] ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์์กด์ฑ์ ๊ด๋ฆฌํ๋ ๋ฒ init, property, method (0) | 2022.05.05 |
[Swift] ์์กด์ฑ ์ฃผ์ ์ ํ์ํ ๊น? DI ์์๋ณด๊ธฐ (0) | 2022.04.29 |
[Swift] insetBy ์์๋ณด๊ธฐ (0) | 2022.04.23 |
๋๊ธ