SwiftUI:手势和偏移不能按预期工作

时间:2019-08-14 04:30:17

标签: offset gesture swiftui

我正在使用偏移量和手势修饰符在屏幕上移动一个圆圈。当我使用此代码时,一切都会按预期进行:

import SwiftUI

struct MovingCircle: View {

@State private var dragged = CGSize.zero

var body: some View {
    Circle()
        .offset(x: self.dragged.width)
        .frame(width: 20, height: 20)
        .gesture(DragGesture()
            .onChanged{ value in
                self.dragged = value.translation
        }
        .onEnded{ value in
            self.dragged = CGSize.zero
            }
    )
 }
}

但是,我不想将圆重置为onEnded的原始位置。我希望它保持原位,然后在拖动时再次移动。当我使用以下代码时,在重新拖动时,我失去了再次移动圆环的功能,并且圆环仍保持在原处:

import SwiftUI

struct MovingCircle: View {

@State private var dragged = CGSize.zero

var body: some View {
    Circle()
        .offset(x: self.dragged.width)
        .frame(width: 20, height: 20)
        .gesture(DragGesture()
            .onChanged{ value in
                self.dragged = value.translation
        }
        .onEnded{ value in
            self.dragged = value.translation
            }
    )
}
}

这是什么原因,我是否遇到了一些错误或编码不正确?

2 个答案:

答案 0 :(得分:1)

首先,要了解该问题,请在.border(Color.red)修饰符中添加一个.frame()

.frame(width: 20, height: 20).border(Color.red)

您将看到,当移动点时,其框架仍保留在原位。这就是为什么以后它不会响应手势的原因。 “可敲击”区域不再与点匹配。而且由于内容区域现在为空,因此不再是“可插拔的”。

要使框架随点移动,请颠倒顺序。 .offset()应该稍后出现:

.frame(width: 20, height: 20).border(Color.red)
.offset(x: self.dragged.width)

最后,您会看到在每个.onEnded()之后,整个事情都会重置。解决此问题的一种方法是,累积您在以前的手势中拖了多少:

struct MovingCircle: View {

    @State private var dragged = CGSize.zero
    @State private var accumulated = CGSize.zero

    var body: some View {
        Circle()
            .frame(width: 20, height: 20).border(Color.red)
            .offset(x: self.dragged.width)

            .gesture(DragGesture()
                .onChanged{ value in
                    self.dragged = CGSize(width: value.translation.width + self.accumulated.width, height: value.translation.height + self.accumulated.height)
            }
            .onEnded{ value in
                self.dragged = CGSize(width: value.translation.width + self.accumulated.width, height: value.translation.height + self.accumulated.height)
                self.accumulated = self.dragged
                }
        )
    }
}

答案 1 :(得分:0)

Swift 5.x iOS 13

一种不太优雅的解决方案,如果您不希望看到对象被拖动;您只希望能够拖动它;如果您正在进行很多工作,并且希望节省CPU,则可能更有意义。

显然,您需要为其找到一个更好的起始位置,然后再使其变为绝对零。

import SwiftUI

var intern:CGPoint = CGPoint(x:0,y:0)

enum DragState {
  case inactive
  case dragging(translation: CGSize)
}

struct ContentView: View {

@State var position:CGPoint = CGPoint(x:0,y:0)
@GestureState private var dragState = DragState.inactive

var body: some View {
 ZStack {
    Circle()
   .frame(width: 24, height: 24, alignment: .center)
 }.offset(x: self.dragOffset.width, y: self.dragOffset.height)
  .gesture(DragGesture(coordinateSpace: .global)
    .updating($dragState, body: { (drag, state, translation) 
      intern = drag.location
    })
    .onEnded { ( value ) in
      self.position = intern
    }
  ).position(position)
 }
}