-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Style] 바텀시트 제스처 따라 수정 #59
base: juri
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,7 +48,7 @@ struct BottomSheetListItem: View { | |
) | ||
} | ||
.layoutPriority(1) | ||
|
||
//Todo: 실제 이미지로 교체 | ||
RoundedRectangle(cornerRadius: 8) | ||
.fill(Color.gray.opacity(0.1)) | ||
|
@@ -64,8 +64,9 @@ struct BottomSheetListView: View { | |
@State private var currentStyle: BottomSheetStyle = .minimal | ||
@State private var offset: CGFloat = 0 | ||
@GestureState private var isDragging: Bool = false | ||
@State private var scrollOffset: CGFloat = 0 | ||
@State private var firstItemFrame: CGRect = .zero | ||
|
||
// 각 상태별 높이값을 저장 | ||
private var snapPoints: [CGFloat] { | ||
[ | ||
BottomSheetStyle.minimal.height, | ||
|
@@ -78,14 +79,12 @@ struct BottomSheetListView: View { | |
let screenHeight = UIScreen.main.bounds.height | ||
let currentHeight = screenHeight - offset | ||
|
||
// 현재 높이와 각 스냅 포인트와의 거리를 계산 | ||
let distances = [ | ||
(abs(currentHeight - BottomSheetStyle.minimal.height), BottomSheetStyle.minimal), | ||
(abs(currentHeight - BottomSheetStyle.half.height), BottomSheetStyle.half), | ||
(abs(currentHeight - BottomSheetStyle.full.height), BottomSheetStyle.full) | ||
] | ||
|
||
// 가장 가까운 스냅 포인트 반환 | ||
return distances.min(by: { $0.0 < $1.0 })?.1 ?? .minimal | ||
} | ||
|
||
|
@@ -107,19 +106,49 @@ struct BottomSheetListView: View { | |
.background(Color.white) | ||
|
||
// 컨텐츠 영역 | ||
ScrollView { | ||
LazyVStack(spacing: 0) { | ||
ForEach(0..<5) { _ in | ||
BottomSheetListItem( | ||
title: "상호명", | ||
subTitle: "주소", | ||
cellTitle: "제목 셀", | ||
hasChip: true | ||
) | ||
Divider() | ||
ScrollView(showsIndicators: false) { | ||
VStack(spacing: 0) { | ||
LazyVStack(spacing: 0) { | ||
ForEach(0..<20) { index in | ||
BottomSheetListItem( | ||
title: "상호명", | ||
subTitle: "주소", | ||
cellTitle: "제목 셀", | ||
hasChip: true | ||
) | ||
.background( | ||
GeometryReader { itemGeometry in | ||
Color.clear.onAppear { | ||
if index == 0 { | ||
firstItemFrame = itemGeometry.frame(in: .named("scrollView")) | ||
} | ||
} | ||
.onChange(of: itemGeometry.frame(in: .named("scrollView"))) { _, newFrame in | ||
if index == 0 { | ||
firstItemFrame = newFrame | ||
|
||
// 첫 번째 셀의 위치에 따라 바텀시트 상태 변경 | ||
let threshold: CGFloat = -30 | ||
if newFrame.minY < threshold && currentStyle == .half { | ||
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { | ||
currentStyle = .full | ||
} | ||
} else if newFrame.minY > threshold && currentStyle == .full { | ||
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { | ||
currentStyle = .half | ||
} | ||
} | ||
} | ||
} | ||
} | ||
) | ||
Divider() | ||
} | ||
Comment on lines
+109
to
+146
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style이 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 의도한건 이게 맞긴합니다. 그런데 기획과 상의가 있어야 할것같아요 상의후 다시 말씀드리겟습니다 |
||
} | ||
Color.clear.frame(height: 90) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. adjust 해주세요! |
||
} | ||
} | ||
.coordinateSpace(name: "scrollView") | ||
.disabled(currentStyle == .minimal) | ||
} | ||
.frame(maxHeight: .infinity) | ||
|
@@ -134,6 +163,7 @@ struct BottomSheetListView: View { | |
.onChanged { value in | ||
let translation = value.translation.height | ||
|
||
// full 상태에서는 위로 드래그 방지 (translation이 음수일 때) | ||
if currentStyle == .full && translation < 0 { | ||
offset = 0 | ||
} else { | ||
|
@@ -166,7 +196,6 @@ struct BottomSheetListView: View { | |
currentStyle = getClosestSnapPoint(to: currentOffset) | ||
} | ||
|
||
// 오프셋 초기화 | ||
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { | ||
offset = 0 | ||
} | ||
|
@@ -177,6 +206,12 @@ struct BottomSheetListView: View { | |
} | ||
} | ||
|
||
struct ScrollOffsetPreferenceKey: PreferenceKey { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 친구가 하는 역할이 뭔가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 원래 스크롤 오프셋 따라 0번째 셀의 위치를 조정햇었는데 현재는 geometry로 조정중이여서 필요없는 코드가 맞습니다 |
||
static var defaultValue: CGFloat = 0 | ||
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { | ||
value = nextValue() | ||
} | ||
} | ||
#Preview { | ||
Home() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VStack 안에 LazyVStack을 넣은 이유가 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다시 찾아보니 LazyStack으로 한번에 다 할수 있는거군요? 저는 원래 이렇게 사용해야한는줄 알앗어요ㅠ