我试图使一个视图可以在其剪裁容器视图内拖动和/或缩放(否则它可能会与其他视图的手势冲突),但到目前为止,我所尝试过的方法都没有防止手势超出容器可见边界。
以下是一个简化的演示,展示了我不想要的行为...
当红色矩形部分超出绿色VStack区域(被裁剪)时,它会响应超出绿色区域的拖动手势:
你如何将此手势限制为仅在容器内(上图中的绿色区域)起作用?
更新: @Asperi的解决方案很好,但是当我在上面添加第二个可拖动容器时,我在第一个容器内部得到了一个“死区”,我无法拖动它(如果第二个正方形不被裁剪,则会覆盖第一个)。问题仅发生在原始/左侧,而不是新的右侧。我认为这与它具有更高优先级有关,因为它是第二个绘制的。
以下是新问题的说明: 以下是更新后的代码:
以下是一个简化的演示,展示了我不想要的行为...
当红色矩形部分超出绿色VStack区域(被裁剪)时,它会响应超出绿色区域的拖动手势:
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
@State var position: CGPoint = CGPoint(x: 100, y: 150)
@State var lastPosition: CGPoint = CGPoint(x: 100, y: 150)
var body: some View {
let drag = DragGesture()
.onChanged {
self.position = CGPoint(x: $0.translation.width + self.lastPosition.x, y: $0.translation.height + self.lastPosition.y)
}
.onEnded {_ in
self.lastPosition = self.position
}
return VStack {
Rectangle().foregroundColor(.red)
.frame(width: 150, height: 150)
.position(self.position)
.gesture(drag)
.clipped()
}
.background(Color.green)
.frame(width: 200, height: 300)
}
}
PlaygroundPage.current.setLiveView(ContentView())
你如何将此手势限制为仅在容器内(上图中的绿色区域)起作用?
更新: @Asperi的解决方案很好,但是当我在上面添加第二个可拖动容器时,我在第一个容器内部得到了一个“死区”,我无法拖动它(如果第二个正方形不被裁剪,则会覆盖第一个)。问题仅发生在原始/左侧,而不是新的右侧。我认为这与它具有更高优先级有关,因为它是第二个绘制的。
以下是新问题的说明: 以下是更新后的代码:
struct ContentView: View {
@State var position1: CGPoint = CGPoint(x: 100, y: 150)
@State var lastPosition1: CGPoint = CGPoint(x: 100, y: 150)
let dragArea1: CGRect = CGRect(x: 0, y: 0, width: 200, height: 300)
@State var position2: CGPoint = CGPoint(x: 100, y: 150)
@State var lastPosition2: CGPoint = CGPoint(x: 100, y: 150)
let dragArea2: CGRect = CGRect(x: 0, y: 0, width: 200, height: 300)
var body: some View {
let drag1 = DragGesture(coordinateSpace: .named("dragArea1"))
.onChanged {
guard self.dragArea1.contains($0.startLocation) else { return }
self.position1 = CGPoint(x: $0.translation.width + self.lastPosition1.x, y: $0.translation.height + self.lastPosition1.y)
}
.onEnded {_ in
self.lastPosition1 = self.position1
}
let drag2 = DragGesture(coordinateSpace: .named("dragArea2"))
.onChanged {
guard self.dragArea2.contains($0.startLocation) else { return }
self.position2 = CGPoint(x: $0.translation.width + self.lastPosition2.x, y: $0.translation.height + self.lastPosition2.y)
}
.onEnded {_ in
self.lastPosition2 = self.position2
}
return HStack {
VStack {
Rectangle().foregroundColor(.red)
.frame(width: 150, height: 150)
.position(self.position1)
.gesture(drag1)
.clipped()
}
.background(Color.green)
.frame(width: dragArea1.width, height: dragArea1.height)
VStack {
Rectangle().foregroundColor(.blue)
.frame(width: 150, height: 150)
.position(self.position2)
.gesture(drag2)
.clipped()
}
.background(Color.yellow)
.frame(width: dragArea2.width, height: dragArea2.height)
}
}
}
有什么想法可以在任何容器外保持拖动禁用,就像已经实现的那样,但同时允许在每个容器的完整边界内进行拖动,而不管其他容器发生了什么?