-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathEmotionCollectionViewLayout.swift
More file actions
96 lines (72 loc) · 3.35 KB
/
EmotionCollectionViewLayout.swift
File metadata and controls
96 lines (72 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//
// EmotionCollectionViewLayout.swift
// Presentation
//
// Created by 이동현 on 8/19/25.
//
import UIKit
final class EmotionCollectionViewLayout: UICollectionViewFlowLayout {
private enum Layout {
static let itemWidthRatio: CGFloat = 0.5
static let lineSpacing: CGFloat = 16
static let bottomSpacing: CGFloat = 100
}
private var baseDistance: CGFloat { itemSize.width + minimumLineSpacing }
override class var layoutAttributesClass: AnyClass { EmotionCollectionViewLayoutAttributes.self }
override func prepare() {
super.prepare()
guard let collectionView else { return }
scrollDirection = .horizontal
minimumLineSpacing = Layout.lineSpacing
let itemWidth = floor(collectionView.bounds.width * Layout.itemWidthRatio)
let itemHeight = collectionView.bounds.height - Layout.bottomSpacing
itemSize = CGSize(width: itemWidth, height: itemHeight)
let insetX = (collectionView.bounds.width - itemWidth) / 2
sectionInset = UIEdgeInsets(
top: 0,
left: insetX,
bottom: Layout.bottomSpacing,
right: insetX)
collectionView.decelerationRate = .fast
}
override func targetContentOffset(forProposedContentOffset proposed: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView else { return proposed }
let visibleRect = CGRect(
origin: CGPoint(x: proposed.x, y: collectionView.contentOffset.y),
size: collectionView.bounds.size)
guard
let layoutAttributesList = super.layoutAttributesForElements(in: visibleRect),
!layoutAttributesList.isEmpty
else { return proposed }
// 화면 중앙에 가장 가까운 셀 찾기
let centerX = proposed.x + collectionView.bounds.width / 2
let closestTarget = layoutAttributesList.min { abs($0.center.x - centerX) < abs($1.center.x - centerX) }
guard let closestTarget else { return proposed }
let newX = closestTarget.center.x - collectionView.bounds.width / 2
return CGPoint(x: newX, y: proposed.y)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard
let collectionView,
let baseAttributesList = super.layoutAttributesForElements(in: rect)
else { return super.layoutAttributesForElements(in: rect) }
let centerX = collectionView.contentOffset.x + collectionView.bounds.width / 2
return baseAttributesList.map { base in
guard let copied = base.copy() as? EmotionCollectionViewLayoutAttributes else { return base }
let distanceFromCenter = abs(copied.center.x - centerX)
let t = min(distanceFromCenter / baseDistance, 1)
copied.progress = 1 - t
return copied
}
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
func fetchcurrentIndex() -> Int? {
guard let collectionView else { return nil }
let centerX = collectionView.contentOffset.x + (collectionView.bounds.width / 2)
let insetX = (collectionView.bounds.width - itemSize.width) / 2
let relativeX = centerX - insetX
return Int(round(relativeX / baseDistance))
}
}