SwiftUI - обнаружение отмены DragGesture при поднятии док-станции iPad

Вот очень простой пример, показывающий, что я пытаюсь делать. Красный круг можно перетаскивать, и когда он отпущен, он вернется в исходное место, как показано на первом изображении. Проблема возникает, когда док-станция iPad поднимается во время перетаскивания, а затем перетаскивается.onEndedникогда не будет вызван, и красный кружок застрянет, как показано на втором изображении. Я не понимаю почему.onEndedне называется. Что мне здесь не хватает?

Я подумал об обходном пути, сбросив offset в SceneDelegate's sceneDidBecomeActive, но это не сработает, если док-станция iPad просто поднята, но приложение не переходит в неактивное состояние, то есть в фоновый режим. В этом случае никакие функции в SceneDelegate не будут вызываться, и я считаю невозможным обнаружить прерывание DragGesture. Любое возможное решение?

struct ContentView: View {
  @State private var offset = CGSize.zero

  var body: some View {
    ZStack {
      Rectangle()
        .fill(Color.clear)
        .frame(width: 100, height: 100)
        .border(Color.black, width: 5)

      Circle()
        .fill(Color.red)
        .frame(width: 90, height: 90)
        .offset(offset)
        .gesture(
          DragGesture()
            .onChanged() { self.offset = $0.translation }
            .onEnded() { _ in self.offset = CGSize.zero })
    }
  }
}

1 ответ

Решение

Попробуйте с GestureStateследующим образом. По умолчанию это временное значение, а по окончании оно сбрасывается до начального значения по умолчанию.

struct ContentView: View {
  @GestureState private var offset = CGSize.zero

  var body: some View {
    ZStack {
      Rectangle()
        .fill(Color.clear)
        .frame(width: 100, height: 100)
        .border(Color.black, width: 5)

      Circle()
        .fill(Color.red)
        .frame(width: 90, height: 90)
        .offset(offset)
        .gesture(
          DragGesture()
            .updating($offset) { (value, gestureState, transaction) in
                gestureState = CGSize(width: value.location.x - value.startLocation.x, height: value.location.y - value.startLocation.y)
            })
    }
  }
}
Другие вопросы по тегам