Drag & Drop은 사용자의 Gesture에 따라 움직이는 뷰를 만들때 사용한다.
Custom으로 뷰를 만들 때 응용하면 아주 좋음!
public struct DragGesture : Gesture { ... }
DragGesture에는 위 두가지 함수가 있음!
그리고 그 함수 내부에서 꺼내 사용할 수 있는 요소들은 아래와 같음!
time: 드래그 제스처의 현재 이벤트와 관련된 시간 정보.
location: 드래그 제스처의 현재 이벤트 위치.
startLocation: 드래그 제스처의 첫 번째 이벤트 위치.
translation: 드래그 제스처의 시작부터 현재 이벤트까지의 전체 이동량. (location.{x,y} - startLocation.{x,y})
velocity: 현재 드래그 속도.
predictedEndLocation: 현재 드래그 속도를 기반으로 드래그가 지금 멈췄을 때 최종 위치의 예측.
predictedEndTranslation: 현재 드래그 속도를 기반으로 드래그가 지금 멈췄을 때 최종 이동량의 예측.
== 함수: 두 DragGesture.Value 값이 동일한지 여부를 판단하는 함수.
나는 translation을 이용해서 만들어 볼 것이다~!
일단 귀엽게 하트 추가 ^0^~
struct DragAndDrop: View {
var body: some View {
VStack {
HeartView
}
}
private var HeartView: some View {
Image(systemName: "suit.heart.fill")
.resizable()
.frame(width: 70, height: 60)
.foregroundStyle(Color.pink)
}
해당 구조체 뷰에만 쓰일거라 구조체 내부에 선언해줬음!
struct DragAndDrop: View {
@State private var dragOffSet = CGSize.zero
@State private var currentOffSet = CGSize.zero
var body: some View {
VStack {
HeartView
.offset(CGSize(width: dragOffSet.width, height: dragOffSet.height))
}
}
private var HeartView: some View {
Image(systemName: "suit.heart.fill")
.resizable()
.frame(width: 70, height: 60)
.foregroundStyle(Color.pink)
}
}
현재 움직인 Offset(dragOffset)과, 움직이기 전의 Offset(currentOffset)을 저장하기 위해 변수를 선언해줌!
그리고 중간으로 zero로 넣어준다.
화면 중심은 0.0이고, 뷰의 offset기준은 뷰의 중심이다.
x좌표는 왼쪽은 음수 오른쪽은 양수 / y좌표는 위쪽은 음수 아래쪽은 양수
struct DragAndDrop: View {
@State private var dragOffSet = CGSize.zero
@State private var currentOffSet = CGSize.zero
var body: some View {
VStack {
HeartView
.offset(CGSize(width: dragOffSet.width, height: dragOffSet.height))
.gesture(
DragGesture()
.onChanged({ gesture in
dragOffSet = CGSize(width: gesture.translation.width + currentOffSet.width, height: gesture.translation.height + currentOffSet.height)
})
.onEnded({ gesture in
dragOffSet = CGSize(width: gesture.translation.width + currentOffSet.width, height: gesture.translation.height + currentOffSet.height)
currentOffSet = dragOffSet
})
)
}
}
private var HeartView: some View {
Image(systemName: "suit.heart.fill")
.resizable()
.frame(width: 70, height: 60)
.foregroundStyle(Color.pink)
}
}
DragGesture를 이용해서 gesture.traslation(CGSize)를 구해준다.
그래서 원래 움직인 Offset과 현재 위치했던 Offset를 더한 후 dragOffset에 넣어주면
HeartView의 위치가 drag에 따라 변한다!
그리고 마지막으로 드래그가 멈췄을 때
currentOffset에 dragOffset을 저장해주면 끝!
멋.지.다.
import SwiftUI
struct DragAndDrop: View {
@State private var dragOffSet = CGSize.zero
@State private var currentOffSet = CGSize.zero
var body: some View {
VStack {
HeartView
.offset(CGSize(width: dragOffSet.width, height: dragOffSet.height))
.gesture(
DragGesture()
.onChanged({ gesture in
calcOffset(gesture.translation)
print(gesture.translation)
})
.onEnded({ gesture in
calcOffset(gesture.translation)
currentOffSet = dragOffSet
})
)
}
}
private var HeartView: some View {
Image(systemName: "suit.heart.fill")
.resizable()
.frame(width: 70, height: 60)
.foregroundStyle(Color.pink)
}
private func calcOffset(_ gestureOffset: CGSize) {
dragOffSet = CGSize(width: gestureOffset.width + currentOffSet.width, height: gestureOffset.height + currentOffSet.height)
}
}
#Preview {
ContentView()
}
마지막으로 요렇게 함수로 빼줌!
'PROGRAMMING CODE > SWIFT' 카테고리의 다른 글
[SwiftUI] CustomSheet (FullScreen + middle, bottom) 만들기! (0) | 2024.02.21 |
---|---|
[SwiftUI] 버튼 눌러 전화걸기 (0) | 2024.02.18 |
[Swift] KakaoMap 리사이징 공부 + 디바이스 화면잘림, black screen 버그 (삽질 일기) (1) | 2024.02.03 |
[SwiftUI] CoreLocation(사용자 위치정보)사용하기 + tuist (삽질 기록^.^) (0) | 2024.01.31 |
[Tuist] Tuist 버전맞추기 (mise) (0) | 2024.01.25 |