final class ParallaxContentView: UIView {
lazy var collectionView = UICollectionView(
frame: .zero,
collectionViewLayout: ParallaxFlowLayout()
).then {
$0.contentInsetAdjustmentBehavior = .never
$0.dataSource = self
$0.delegate = self
$0.register(ParallaxCell.self, forCellWithReuseIdentifier: "cell")
$0.register(ParallaxHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "header")
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
self.addSubview(self.collectionView)
self.collectionView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}
}
extension ParallaxContentView: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let width: CGFloat = collectionView.frame.width
let height: CGFloat = 480
return CGSize(width: width, height: height)
}
}
extension ParallaxContentView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.width, height: 300)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "header", for: indexPath)
return header
}
}
final class ParallaxFlowLayout: UICollectionViewFlowLayout {
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let layoutAttributes = super.layoutAttributesForElements(in: rect)
guard let offset = collectionView?.contentOffset, let stLayoutAttributes = layoutAttributes else {
return layoutAttributes
}
if offset.y < 0 { // stretchy header 늘어나는 효과....!!!
for attributes in stLayoutAttributes {
if let elmKind = attributes.representedElementKind, elmKind == UICollectionView.elementKindSectionHeader {
let diffValue = abs(offset.y)
var frame = attributes.frame
frame.size.height = max(0, 480 + diffValue)
frame.origin.y = frame.minY - diffValue
attributes.frame = frame
}
}
} else { // 헤더가 점점 화면에서 사라져야 할 때
for attributes in stLayoutAttributes {
if let elmKind = attributes.representedElementKind, elmKind == UICollectionView.elementKindSectionHeader {
let diffValue = abs(offset.y)
var frame = attributes.frame
frame.size.height = max(0, 480 - diffValue)
frame.origin.y = frame.minY + diffValue
attributes.frame = frame
attributes.alpha = 1 - diffValue/480
}
}
}
return layoutAttributes
}
}
class ParallaxCell: UICollectionViewCell {
}
class ParallaxHeaderView: UICollectionReusableView {
let imageView = UIImageView().then {
$0.contentMode = .scaleAspectFill
$0.isUserInteractionEnabled = true
$0.clipsToBounds = true
$0.image = UIImage(named: "product")
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
self.addSubview(self.imageView)
self.imageView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}
}
Created
April 1, 2023 04:58
-
-
Save audrl1010/1d5779df49b056aa03c93d79977f198d to your computer and use it in GitHub Desktop.
parallax scrolling.md
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment