Skip to content

Commit 77e4718

Browse files
committed
ui: 프리뷰 히트맵 부분을 동적 ui화
1 parent c74c85f commit 77e4718

1 file changed

Lines changed: 37 additions & 26 deletions

File tree

DevLog/UI/Profile/HeatmapView.swift

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
import SwiftUI
99

1010
struct HeatmapView: View {
11-
@Environment(\.safeAreaInsets) private var safeAreaInsets
12-
@Environment(\.sceneWidth) private var sceneWidth
11+
@State private var availableWidth = CGFloat.zero
1312
let quarter: HeatmapQuarter
1413
let selectedActivityKinds: Set<ActivityKind>
1514
let selectedDay: HeatmapDay?
@@ -21,31 +20,32 @@ struct HeatmapView: View {
2120
weekCounts: quarter.months.map(\.weeks.count)
2221
)
2322

24-
HStack(alignment: .top, spacing: layout.monthSpacing) {
25-
ForEach(quarter.months) { month in
26-
MonthCompactHeatmapView(
27-
month: month,
28-
maxCount: maxCount,
29-
layout: layout,
30-
selectedActivityKinds: selectedActivityKinds,
31-
selectedDay: selectedDay,
32-
onSelectDay: onSelectDay
33-
)
23+
ScrollView(.horizontal) {
24+
LazyHStack(alignment: .top, spacing: layout.monthSpacing) {
25+
ForEach(quarter.months) { month in
26+
MonthCompactHeatmapView(
27+
month: month,
28+
maxCount: maxCount,
29+
layout: layout,
30+
selectedActivityKinds: selectedActivityKinds,
31+
selectedDay: selectedDay,
32+
onSelectDay: onSelectDay
33+
)
34+
}
35+
}
36+
.padding(.vertical, 2)
37+
.frame(width: layout.contentWidth, alignment: .leading)
38+
}
39+
.scrollIndicators(.hidden)
40+
.scrollDisabled(true)
41+
.frame(maxWidth: .infinity, alignment: .leading)
42+
.background {
43+
GeometryReader { geometry in
44+
Color.clear
45+
.onAppear { updateAvailableWidth(geometry.size.width) }
46+
.onChange(of: geometry.size.width) { updateAvailableWidth($1) }
3447
}
3548
}
36-
.padding(.vertical, 2)
37-
}
38-
39-
private var availableWidth: CGFloat {
40-
// ProfileView의 바깥 가로 패딩(16)과 히트맵 카드 내부 패딩(12)을 합한 값
41-
let horizontalPadding: CGFloat = 16 + 12
42-
return max(
43-
0,
44-
sceneWidth
45-
- safeAreaInsets.leading
46-
- safeAreaInsets.trailing
47-
- (horizontalPadding * 2)
48-
)
4949
}
5050

5151
private var maxCount: Int {
@@ -70,13 +70,22 @@ struct HeatmapView: View {
7070
}
7171
return value
7272
}
73+
74+
private func updateAvailableWidth(_ width: CGFloat) {
75+
if availableWidth != width {
76+
availableWidth = width
77+
}
78+
}
7379
}
7480

7581
private struct HeatmapLayout {
82+
private static let minimumCellSize: CGFloat = 8
83+
private static let maximumCellSize: CGFloat = 22
7684
let cellSize: CGFloat
7785
let cellSpacing: CGFloat = 4
7886
let monthSpacing: CGFloat = 12
7987
let monthTitleSpacing: CGFloat = 6
88+
let contentWidth: CGFloat
8089

8190
init(availableWidth: CGFloat, weekCounts: [Int]) {
8291
let totalColumns = max(weekCounts.reduce(0, +), 1)
@@ -85,7 +94,9 @@ private struct HeatmapLayout {
8594
}
8695
let fixedWidth = monthSpacing * CGFloat(max(weekCounts.count - 1, 0))
8796
+ cellSpacing * CGFloat(totalColumnSpacings)
88-
cellSize = max(0, availableWidth - fixedWidth) / CGFloat(totalColumns)
97+
let fittingCellSize = max(0, availableWidth - fixedWidth) / CGFloat(totalColumns)
98+
cellSize = min(max(fittingCellSize, Self.minimumCellSize), Self.maximumCellSize)
99+
contentWidth = cellSize * CGFloat(totalColumns) + fixedWidth
89100
}
90101

91102
var cellCornerRadius: CGFloat {

0 commit comments

Comments
 (0)