Почему автореверс добавленной анимации «портит» окончательный результат? - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть приложение, которое анимирует маленькое красное подпредставление, используя добавленную анимацию.Первая анимация сдвигает вид вниз на 100 пунктов.Вторая анимация включается на полпути и перемещает вид на 100 пунктов вправо.Анимации вниз и вправо являются аддитивными, что приводит к диагональному движению в нижнем правом углу.Кроме того, обе анимации автоматически реверсируются, поэтому представление восстанавливается в исходное положение поверх небольшого зеленого подпредставления «маркер».

simulator

Из приведенного выше рисунка видно, что анимация представления ведет себя как ожидалось до тех пор, пока не завершится автореверс, после чего представление переместится влево (очевидно, на 100 пунктов).Обычно такой скачок будет результатом отсутствия установки состояния представления в соответствии с последним кадром анимации.Однако состояние представления действительно правильно (?) Устанавливается методом завершения аниматора - это подтверждается информацией, предоставленной операторами print.

Что является причиной окончательного просмотра слевапрыжок?

См. соответствующий код ниже.Полный проект может быть загружен с GitHub

У меня есть догадка, что вызовы UIView.setAnimationRepeatAutoreverses в каждом из двух закрытий анимации могут быть виновником.Мне не ясно, что то, что я сделал в этом отношении, согласуется с ожиданиями структуры.

class ViewController: UIViewController {

    private var markerView: UIView!
    private var animationView: UIView!

    override func viewDidLoad() {
        view.backgroundColor = .black
        view.addGestureRecognizer(UITapGestureRecognizer.init(target: self, action: #selector(tapGestureHandler)))

        let frame = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 10, height: 10)

        markerView = UIView(frame: frame)
        markerView.backgroundColor = .green
        view.addSubview(markerView)

        animationView = UIView(frame: frame)
        animationView.backgroundColor = .red
        view.addSubview(animationView)
    }

    @objc private func tapGestureHandler(_ sender: UITapGestureRecognizer) {
        animate()
    }

    // Move down; half way through begin moving right while still moving down.
    // Autoreverse it.
    private func animate() {
        let distance: CGFloat = 100
        let down = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.y += distance
        }
        let right = {
            UIView.setAnimationRepeatAutoreverses(true)
            self.animationView.center.x += distance
        }

        print("\nCenter: \(self.animationView.center)")

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            self.animationView.center.x -= distance
            self.animationView.center.y -= distance
            print("Center: \(self.animationView.center)")
        }
        animator.startAnimation()
    }
}

Обновление 1

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

animate2: вызовы UIView.setAnimationRepeatAutoreverses были закомментированы в каждой из нижних и правых функций анимации.Этот модифицированный код функционирует как ожидалось.Конечно, мы не получаем плавный автореверсивный эффект.

extension ViewController {

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

        print("\nCenter: \(self.animationView.center)")

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            self.animationView.center.x -= distance
            self.animationView.center.y -= distance
            print("Center: \(self.animationView.center)")
        }
        animator.startAnimation()
    }
}

enter image description here

animate3: добавлено добавление второй (то есть правой) анимации,Этот модифицированный код функционирует как ожидалось.Конечно, мы не получаем движение вправо.

extension ViewController {

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

        print("\nCenter: \(self.animationView.center)")

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        //animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            self.animationView.center.y -= distance
            //self.animationView.center.x -= distance
            print("Center: \(self.animationView.center)")
        }
        animator.startAnimation()
    }
}

enter image description here

Похоже, что вызов UIView.setAnimationRepeatAutoreverses в обеих функциях анимации"испортить вещи".Мне не ясно, можно ли это по праву считать ошибкой iOS.

1 Ответ

0 голосов
/ 08 февраля 2019

Просто прокомментируйте строку под вашим методом animate () ::

        let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: down)
        animator.addAnimations(right, delayFactor: 0.5)
        animator.addCompletion { _ in
            print("Center: \(self.animationView.center)")
            //self.animationView.center.x -= distance //<--- Comment or remove this line.
            self.animationView.center.y -= distance
            print("Center: \(self.animationView.center)")
        }
...