如何使用SwiftUI使按钮可拖动/移动?

如何使用SwiftUI使按钮可拖动/移动?,swift,xcode,swift5.2,swiftui,Swift,Xcode,Swift5.2,Swiftui,我正在尝试使一个按钮可以用SwiftUI移动。从表面上看,这应该是可行的。我曾尝试将带有文本的按钮放在另一个ZStack中,有一秒钟它工作正常,但我一松开按钮,拖动就停止了,我无法再拖动了。我注意到,尽管按钮移动了,但水龙头仍保持在中间。而且拖拉的车看起来像是四轮马车 struct CircleButton: View { @State private var dragAmount = CGSize.zero var body: some View { ZStack {

我正在尝试使一个按钮可以用SwiftUI移动。从表面上看,这应该是可行的。我曾尝试将带有文本的按钮放在另一个ZStack中,有一秒钟它工作正常,但我一松开按钮,拖动就停止了,我无法再拖动了。我注意到,尽管按钮移动了,但水龙头仍保持在中间。而且拖拉的车看起来像是四轮马车

 struct CircleButton: View {
@State private var dragAmount = CGSize.zero
var body: some View {
    ZStack {
        Button(action: performAction){
            ZStack {
                Circle()
                    .foregroundColor(.blue)
                    .frame(width: 100, height: 100)
                Text("Move me")
                    .foregroundColor(.white)
                    .font(.system(.caption, design: .serif))
            }
        }
        .animation(.default)
        .offset(self.dragAmount)
    }
    .gesture(
        DragGesture()
            .onChanged { self.dragAmount = $0.translation})
}

func performAction(){
    print("button pressed")
 }
}
我试过这个:

struct CircleButton: View {
@State private var dragAmount = CGSize.zero
var body: some View {
    ZStack {
        ZStack {
            Button(action: performAction){
                Circle()
                    .foregroundColor(.blue)
                    .frame(width: 100, height: 100)
            }
            Text("Tap me")
        }
        .offset(self.dragAmount)
        .animation(.default)
    }
    .gesture(
        DragGesture()
            .onChanged{ self.dragAmount = $0.translation})
}

func performAction(){
    print("button pressed")
 }
}

下面是一个可能方法的演示。使用Xcode 11.4/iOS 13.4进行测试和工作

另请参见注释内联

struct CircleButton: View {
    @State private var dragAmount: CGPoint?
    var body: some View {
        GeometryReader { gp in // just to center initial position
            ZStack {
                Button(action: self.performAction) {
                    ZStack {
                        Circle()
                            .foregroundColor(.blue)
                            .frame(width: 100, height: 100)
                        Text("Move me")
                            .foregroundColor(.white)
                            .font(.system(.caption, design: .serif))
                    }
                }
                .animation(.default)
                .position(self.dragAmount ?? CGPoint(x: gp.size.width / 2, y: gp.size.height / 2))
                .highPriorityGesture(  // << to do no action on drag !!
                    DragGesture()
                        .onChanged { self.dragAmount = $0.location})
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity) // full space
        }
    }

    func performAction() {
        print("button pressed")
    }
}
struct CircleButton:视图{
@国家私有var dragAmount:CGPoint?
var body:一些观点{
GeometryReader{gp in//刚好到中心初始位置
ZStack{
按钮(动作:自我执行){
ZStack{
圈()
.foregroundColor(.blue)
.框架(宽度:100,高度:100)
文本(“移动我”)
.foregroundColor(.白色)
.font(.system(.caption,design:.serif))
}
}
.animation(.default)
.位置(自dragAmount??CGPoint(x:gp.size.width/2,y:gp.size.height/2))

.highprioritysignature(//做些不同的简洁的事情怎么样:

import SwiftUI

struct ContentView: View {
var body: some View {
    CircleButton()
}
}

struct CircleButton: View {

@State private var pos = CGPoint(x:222,y:222) // just for testing

var body: some View {
    theButton.position(self.pos).highPriorityGesture(self.drag)
}

var theButton: some View {
    ZStack {
        Circle()
            .foregroundColor(.blue)
            .frame(width: 100, height: 100)
            .onTapGesture { self.performAction() }
        Text("Tap me")
            .foregroundColor(.white)
            .font(.system(.caption, design: .serif))
    }
}

func performAction(){
    print("button pressed")
}

var drag: some Gesture {
    DragGesture().onChanged { value in self.pos = CGPoint(x: value.location.x, y: value.location.y)}
}
}

我在这里找到了一个简单的解决方案。只需一个ViewModifier和一个扩展:

struct DraggablePita: View {
  var body: some View {
    Image(uiImage: UIImage(named: "pita.png")!)
      .draggable() // Add the new, custom modifier to make this draggable
  }
}

// Handle dragging
struct DraggableView: ViewModifier {
  @State var offset = CGPoint(x: 0, y: 0)

  func body(content: Content) -> some View {
    content
      .gesture(DragGesture(minimumDistance: 0)
        .onChanged { value in
          self.offset.x += value.location.x - value.startLocation.x
          self.offset.y += value.location.y - value.startLocation.y
      })
      .offset(x: offset.x, y: offset.y)
  }
}

// Wrap `draggable()` in a View extension to have a clean call site
extension View {
  func draggable() -> some View {
    return modifier(DraggableView())
  }
}

一个问题:当我删除.frame()时你在底部添加的方法,我注意到结果是一样的。是否有必要使用它的原因?我看到它旁边的注释写满了空格,但我不确定它的意思。@OcielLerma,它仍然是最初尝试时使用的,没有使用GeometryReader,因此如果要删除它,应该是这样的。但是如果你保持它不变,t当您可以安全地删除.frame修改器时,请使用
.animation(.none)
停止拖动