[英]SwiftUI DragGesture only in one direction
我希望 SwiftUI DragGesture 僅在手勢處於特定方向(水平/垂直)時啟動。 是否可以?
是的,它是通過將手勢轉換的兩個組件(水平或垂直)之一應用於視圖偏移量。
這是作為ViewModifier
實現的這種行為。
struct DraggableModifier : ViewModifier {
enum Direction {
case vertical
case horizontal
}
let direction: Direction
@State private var draggedOffset: CGSize = .zero
func body(content: Content) -> some View {
content
.offset(
CGSize(width: direction == .vertical ? 0 : draggedOffset.width,
height: direction == .horizontal ? 0 : draggedOffset.height)
)
.gesture(
DragGesture()
.onChanged { value in
self.draggedOffset = value.translation
}
.onEnded { value in
self.draggedOffset = .zero
}
)
}
}
演示:
struct ContentView: View {
var body: some View {
VStack {
Spacer(minLength: 100)
HStack {
Rectangle()
.foregroundColor(.green)
.frame(width: 100, height: 100)
.modifier(DraggableModifier(direction: .vertical))
Text("Vertical")
}
Spacer(minLength: 100)
Rectangle()
.foregroundColor(.red)
.frame(width: 100, height: 100)
.modifier(DraggableModifier(direction: .horizontal))
Text(verbatim: "Horizontal")
Spacer(minLength: 100)
}
}
}
結果:
相當老的問題,但在其他地方找不到答案。
您可以輕松檢查它是向左滑動還是向右滑動,因為手勢返回其結尾 state,其中包含起始和最終 position。
Text("Hello").gesture(DragGesture(minimumDistance: 100).onEnded { endedGesture in
if (endedGesture.location.x - endedGesture.startLocation.x) > 0 {
print("Left")
} else {
print("Right")
}
}
如果手勢移動水平移動而不是垂直移動,這只會移動視圖。 isDragging boolean 確保滿足第一個條件后,視圖也會垂直移動。 這不是必需的,但它有助於更平滑的拖動。
@State var dragOffset: CGSize = .zero
@State var isDragging = false
.offset(x: offset.width, y: offset.height)
.gesture(DragGesture()
.onChanged { if abs($0.translation.width) > abs($0.translation.height) || isDragging {
self.offset = $0.translation
self.isDragging = true
}
}
.onEnded {
isDragging = false
})
一個例子,在運動開始時,確定垂直或水平運動,之后 object 僅在這個方向上運動
struct Test: View {
@State private var offsetX = CGFloat.zero
@State private var offsetY = CGFloat.zero
var body: some View {
ZStack {
Divider()
Divider().rotationEffect(.degrees(90))
Divider().rotationEffect(.degrees(45))
Divider().rotationEffect(.degrees(-45))
VStack {
Spacer()
Text("offsetX: \(offsetX) offsetY: \(offsetY)")
.foregroundColor(.black.opacity(0.5))
.frame(maxWidth: .infinity)
.padding(.bottom, 18.0)
}
Rectangle()
.fill(.green)
.frame(width: 300.0, height: 200.0)
.cornerRadius(13.0)
.offset(x: offsetX, y: offsetY)
.gesture(drag)
}
}
@State private var horizontal = true
@State private var vertical = true
var drag: some Gesture {
DragGesture()
.onChanged { dg in
var x = dg.translation.width
var y = dg.translation.height
if ((x < 0 && y < 0 && x < y) || (x < 0 && y > 0 && -x > y) || (x > 0 && y < 0 && x > -y) || (x > 0 && y > 0 && x > y)) && self.horizontal && self.vertical {
self.horizontal = true
self.vertical = false
} else if vertical && horizontal {
self.horizontal = false
self.vertical = true
}
if self.horizontal {
self.offsetX = x
} else {
self.offsetY = y
}
}
.onEnded { _ in
withAnimation {
self.offsetX = .zero
self.offsetY = .zero
}
self.horizontal = true
self.vertical = true
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.