Почему окончательная презентация результата анимации не соответствует ожиданиям? - PullRequest
0 голосов
/ 07 апреля 2020

Следующий gif демонстрирует проблему с анимацией, которая у меня возникла. Маленький красный вид анимирован. Маленький зеленый вид обозначает начальную позицию. Красный вид анимируется вниз и вправо, а затем автоматически переворачивается. В конце, после возврата в исходное положение, красный вид переходит влево: именно этот прыжок я не понимаю.

enter image description here

Вот код Анимация состоит из двух частей: первоначальное изменение положения Y и изменение положения X, которое выполняется на полпути. Обе анимации автоматически меняются местами. Обратите внимание на закрытие завершения, которое обновляет модель, чтобы отразить окончательную позицию представления, которая была вызвана автоматическим реверсированием. Мне все кажется правильным. Почему прыжок влево?

    @objc private func animate() {

        let center = animationView.center

        let distance: CGFloat = 100
        let down = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.y += distance
        }
        let right = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.x += distance
        }

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in self.animationView.center = center } // Sync up with result of the autoreverse
        animator.startAnimation()
    }
  1. Кажется, что прыжок влево составляет 100 баллов (аналогично анимированному изменению позиции)
  2. Проблема, похоже, связана с вторая часть анимации. Если я не добавлю его и вместо этого изменю X в первой части (где Y изменен), то все будет хорошо.
  3. Когда после завершения анимации я проверяю центр красного представления, я нахожу, что это " правильный"; он равен центру root вида. Другими словами: модель и представление не совпадают ???
  4. Когда я использую возможность иерархии отладки представления XCode, красный вид изображается как находящийся в центре экрана

// *********************************************** ************************

Обновление № 1: анимация состоит из двух частей; вниз и вправо. В каждой из этих двух частей я вызываю UIView.setAnimationRepeatAutoreverse. Если я закомментирую одно или оба из этих автореверсивов, тогда все будет работать как положено (хотя я не получаю эффекта автореверсирования, но поведение кода понятно).

// ** ************************************************** *******************

Обновление № 2: из документации Apple UIView.setAnimationRepeatAutoreverse: использование этого метода не рекомендуется в iOS 4.0 и более поздних версиях , Вместо этого вы должны использовать метод animate (withDuration: delay: options: animations: creation :) для указания ваших анимаций и параметров анимации.

Хорошо. Давайте посмотрим, что еще доступно для выполнения sh задержки второй части анимации.

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

Наконец-то!

private func animate() {

    let distance: CGFloat = 100
    let down = { self.animationView.center.y += distance }
    let right = { self.animationView.center.x += distance }

    let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
    animator.addAnimations(right, delayFactor: 0.5)
    animator.pausesOnCompletion = true
    let observer = animator.observe(\.isRunning, options: [.new] ) { animator, change in
        print("isRunning changed to \(change.newValue!).")

        if !animator.isRunning {
            if !animator.isReversed {
                print("Reversing animation")
                animator.isReversed = true;
                animator.startAnimation()
            }
            else {
                print("Stopping animation")
                animator.stopAnimation(false)
                animator.finishAnimation(at: .start)
            }
        }
    }
    animator.addCompletion { position in
        print("Animation completed at \(position). State = \(animator.state).")
        observer.invalidate() // By capturing the observer here in the completion closure we keep it alive for the duration of the animation.
    }

    print("\nStarting animation")
    animator.startAnimation()
    print("Animation started")
}
0 голосов
/ 10 апреля 2020

Использовать старый API

    @objc private func animate() {

        let original = animationView.center

        let distance: CGFloat = 100
        let down = { self.animationView.center.y += distance }
        let right = { self.animationView.center.x += distance }

        let duration: TimeInterval = 2
        UIView.animate(withDuration: duration, delay: 0, options: .autoreverse, animations: down) { _ in self.animationView.center.y = original.y }
        UIView.animate(withDuration: duration/2, delay: duration/2, options: .autoreverse, animations: right) { _ in self.animationView.center.x = original.x }
    }
...