-
Notifications
You must be signed in to change notification settings - Fork 0
SwiftUI DragGesture로 구현된 버튼에서 스크롤 제스처 충돌 문제 #10
Copy link
Copy link
Open
Description
Describe the bug
SwiftUI에서 버튼의 pressed 상태를 구현하기 위해 DragGesture를 사용할 때 발생하는 스크롤 제스처 충돌 문제
- 스크롤 가능한 영역(ScrollView) 내에 배치된 버튼에서 사용자가 스크롤을 시도하면,
- 버튼의
DragGesture가 스크롤 제스처를 차단하여 스크롤이 되지 않음
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
stateType = .pressed
}
.onEnded { _ in
stateType = .normal
action()
}
)Cause
-
DragGesture(minimumDistance: 0)을 사용하여 터치 즉시 드래그 제스처가 인식됨 -
onChanged와onEnded에서 이동 거리나 방향을 고려하지 않고 모든 드래그 동작을 버튼 액션으로 처리 -
결과적으로 스크롤뷰의 제스처가 완전히 차단 -> 사용자가 의도한 스크롤 동작을 수행할 수 없음
Solution
-
.gesture()->.simultaneousGesture()로 변경하여 스크롤과 버튼 제스처가 동시에 작동하도록 수정simultaneousGesture(_:including:)공식 문서
-
이동 거리 기반 로직을 추가하여 탭과 스크롤을 구분
-
onChanged: 이동 거리가 10px 미만이면 pressed 상태 유지, 10px 이상이면 pressed 해제 -
onEnded: 최종 이동 거리가 10px 미만일 때만 버튼 액션 실행
-
버튼을 누른 채로 드래그하면 pressed 상태가 해제되고 스크롤만 실행됨
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { value in
let distance = calculateDistance(from: value.translation)
// 임계값 10px
if distance < 10 {
stateType = .pressed
} else {
// 스크롤이 시작되면 pressed 해제
stateType = .normal
}
}
.onEnded { value in
let distance = calculateDistance(from: value.translation)
// pressed 상태였고 이동이 작으면 액션 실행
if distance < 10 {
action()
}
stateType = .normal
}
)
/// CGSize에서 이동 거리를 계산
private func calculateDistance(from translation: CGSize) -> CGFloat {
return sqrt(pow(translation.width, 2) + pow(translation.height, 2))
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels