以下代码显示了一个橙色屏幕,在右下方有一个绿色圆圈。圆圈可以拖动。
import SwiftUI
struct DraggableCircle: View {
@Binding var offset: CGSize
@State private var previousOffset: CGSize
var body: some View {
Circle().fill(Color.green)
.frame(width: 100)
.offset(self.offset)
.gesture(
DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged { event in
print("\nDragGesture onChanged")
self.offset = CGSize(width: event.location.x - (event.startLocation.x - self.previousOffset.width),
height: event.location.y - (event.startLocation.y - self.previousOffset.height))
}
)
}
init(offset: Binding<CGSize>) {
print("Init with offset \(offset.wrappedValue)")
self._offset = offset
self._previousOffset = State(initialValue: offset.wrappedValue)
print("offset = \(self.offset), previousOffset=\(self.previousOffset)")
}
}
struct ContentView: View {
@State var circleOffset = CGSize()
var body: some View {
GeometryReader { reader in
Rectangle().fill(Color.orange)
.overlay(
DraggableCircle(offset: self.$circleOffset)
)
.onAppear {
self.circleOffset = CGSize(width: reader.size.width / 2,
height: reader.size.height / 2)
print("size: \(reader)\n")
}
}
}
}
如果您运行并点击绿色圆圈(以开始拖动手势),控制台中将显示以下内容:
Init with offset (0.0, 0.0)
offset = (0.0, 0.0), previousOffset=(0.0, 0.0)
size: GeometryProxy(base: SwiftUI._PositionAwareLayoutContext(base: SwiftUI.LayoutTraitsContext(context: AttributeGraph.AttributeContext<SwiftUI.VoidAttribute>(graph: __C.AGGraphRef(p: 0x00007f84b6a05ff0), attribute: AttributeGraph.Attribute<()>(identifier: __C.AGAttribute(id: 42))), environmentIndex: 4), dimensionsIndex: 1, transformIndex: 3, positionIndex: 2), seed: 1, viewGraph: Optional(SwiftUI.ViewGraph))
Init with offset (187.5, 323.5)
offset = (187.5, 323.5), previousOffset=(187.5, 323.5)
DragGesture onChanged
Init with offset (0.0, 0.0)
offset = (0.0, 0.0), previousOffset=(0.0, 0.0)
我希望发生的事情是,当您拖动圆圈时,可以将其平滑地拖动到屏幕上的其他位置。
实际上发生的是,当拖动开始时,再次调用DraggableCircle.init
,这将重置偏移并将圆放置在中间。为什么会这样?
注意:将@State previousOffset
移到ContentView
时,问题消失了。但是我不明白为什么。
答案 0 :(得分:0)
我根据您的评论更改了代码。在我的代码中,此拖动手势可以正常工作。我现在看到的唯一错误是第一次激活拖动手势。也许这会引导您找到所需的解决方案。
struct DraggableCircle: View {
@Binding var circleOffset: CGSize
@State private var previousOffset: CGSize
var body: some View {
Circle().fill(Color.green)
.frame(width: 100)
.offset(self.circleOffset)
.gesture(
DragGesture()
.onChanged { event in
print("\nDragGesture onChanged")
self.circleOffset = CGSize(width: event.location.x - (event.startLocation.x - self.previousOffset.width),
height: event.location.y - (event.startLocation.y - self.previousOffset.height))
}
.onEnded { event in
self.circleOffset = CGSize(width: event.location.x - (event.startLocation.x - self.previousOffset.width),
height: event.location.y - (event.startLocation.y - self.previousOffset.height))
self.previousOffset = self.circleOffset
}
)
}
init(offset: Binding<CGSize>) {
print("Init with offset \(offset.wrappedValue)")
self._circleOffset = offset
self._previousOffset = State(initialValue: offset.wrappedValue)
print("offset = \(self.offset), previousOffset=\(self.previousOffset)")
}
}
struct ContentView: View {
@State var circleOffset = CGSize()
var body: some View {
GeometryReader { reader in
Rectangle().fill(Color.orange)
.overlay(
DraggableCircle(offset: self.$circleOffset)
)
.onAppear {
self.circleOffset = CGSize(width: reader.size.width / 2,
height: reader.size.height / 2)
print("size: \(reader)\n")
}
}
}
}