[英]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.