Как приостановить анимацию в SwiftUI? - PullRequest
0 голосов
/ 21 сентября 2019

Я не знаю, как остановить withAnimation(_:) метод после его запуска.

Я пишу свое первое приложение с SwiftUI и хочу создать круг выполнения, который будет управляться кнопками пользователем- кнопка запуска, которая запускает анимацию, где кружок будет незаполнен в конце, а кнопка остановки должна будет сохранять фактическое состояние точки заливки и останавливать анимацию.

Мой основной вид:

struct MainView: View {
  @State private var fillPoint = 1.0 
  @State private var animationDuration = 10.0

  private var ring: Ring {
    let ring = Ring(fillPoint: self.fillPoint)
    return ring
  }

  var body: some View {
    VStack {
      ring.stroke(Color.red, lineWidth: 15.0)
        .frame(width: 200, height: 200)
        .padding(40)
      HStack {
        Button(action: {
          withAnimation(.easeIn(duration: self.animationDuration)) {
              self.fillPoint = 0
          }
        }) {
          Text("Start")
        }
        Button(action: {
          // what should I do here?
        }) {
          Text("Stop")
        }
      }
    }
  }
}

И структура Ринга:

struct Ring: Shape {
  var startArcAngle: Double = 360.0

  var fillPoint: Double {
    willSet {
      startArcAngle = 360 * newValue
    }
  }

  internal var animatableData: Double {
    get { return fillPoint }
    set { fillPoint = newValue }
  }

  internal func path(in rect: CGRect) -> Path {
    let endArcAngle = 0.0

    var path = Path()

    path.addArc(center: CGPoint(x: rect.size.width / 2,
                                y: rect.size.height / 2),
                radius: rect.size.width / 2,
                startAngle: .degrees(startArcAngle - 90),
                endAngle: .degrees(endArcAngle - 90),
                clockwise: true)

    return path
  }
}

Я пытался манипулировать значением animatableData, но вне структуры Ринга он всегда возвращает 0.0 (значение, которое мой код будет достигать в конце анимацииесли он запущен) и внутри структуры Ring он печатается так, как мне хотелось бы (0.96xxxx -> 0.94xxxx и т. д.), но если взять это вне структуры Ring, всегда возвращается 1.0 или 0.0.

1 Ответ

0 голосов
/ 22 сентября 2019

Похоже, что нет управления для остановки анимации.Поскольку ваше требование состоит в том, чтобы начать и остановить розыгрыш в середине хода, одно альтернативное решение - использовать Таймер .хитрый момент заключается в том, чтобы очистить дугу на основе длительности таймера.Вот код, который я внес в ваш MainView:

ПРИМЕЧАНИЕ. Настройте продолжительность анимации в соответствии с вашим выбором.

struct MainView: View {
  @State private var fillPoint = 1.0
  @State private var animationDuration = 10.0
  @State private var  stopAnimation = true
  @State private var countdownTimer: Timer?

  private var ring: Ring {
    let ring = Ring(fillPoint: self.fillPoint)
    return ring
  }

  var body: some View {
    VStack {
      ring.stroke(Color.red, lineWidth: 15.0)
        .frame(width: 200, height: 200)
        .padding(40)
        .animation(self.stopAnimation ? nil : .easeIn(duration: 0.1))
      HStack {
        Button(action: {
            self.stopAnimation = false
            self.countdownTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
                guard self.animationDuration > 0 else {
                    self.countdownTimer?.invalidate()
                    return
                }
                self.fillPoint = self.animationDuration/10
                self.animationDuration -= 0.1
            })
        }) {
          Text("Start")
        }
        Button(action: {
             self.countdownTimer?.invalidate()
            self.stopAnimation = true

        }) {
            Text("Stop")
        }
      }
    }
  }
}    
...