Я изучал очень классный новый класс UIViewPropertyAnimator
в iOS 10. Он позволяет легко делать такие вещи, как пауза, возобновление и обратная анимация UIView во время полета. Раньше было, что вам нужно было манипулировать базовыми CAAnimations, созданной системой, чтобы сделать это с анимацией UIView.
Новый класс UIViewPropertyAnimator
имеет свойство fractionComplete
. Он варьируется от 0.0 (начало анимации) до 1.0 (конец анимации). Если вы измените значение, вы можете "счистить" анимацию от начала до конца.
У меня есть демонстрационный проект на Github, называемый KeyframeViewAnimations, который позволяет использовать слайдер для очистки UIView и CAAnimations назад и вперед, используя довольно тайные трюки CAAnimation. По мере запуска анимации слайдер перемещается от начала и до конца, чтобы показать ход анимации. Этот проект был написан в Objective-C до того, как Swift был выпущен, но основные методы одинаковы в Objective-C или Swift.
Я решил создать эквивалентный проект, используя UIViewPropertyAnimator
. Есть некоторые причуды, но это довольно прямолинейно. Единственное, что я не мог понять, как это сделать, - это наблюдать за развитием анимации fractionComplete
, чтобы я мог обновлять слайдер по мере продвижения анимации. Я попытался настроить KVO (наблюдение за ключом) в свойстве fractionComplete
, но он не вызывает уведомление KVO, пока анимация не будет завершена.
То, что я закончил, это настроить таймер, который выполняется на очень маленьком интервале, и повторно запрашивает свойство UIViewPropertyAnimator
fractionComplete
и обновляет слайдер по мере его продвижения. Это работает, но это не очень чистый способ делать что-то. Было бы намного лучше, если бы был способ получить уведомление о ходе анимации.
Я надеюсь, что там что-то мне не хватает.
Вы можете увидеть проект UIViewPropertyAnimator
на Github по этой ссылке: UIViewPropertyAnimator-test.
Код, который получает значение прогресса от аниматора, - это код:
func startTimer(_ start: Bool) {
if start {
timer = Timer.scheduledTimer(withTimeInterval: 0.02,
repeats: true) {
timer in
var value = Float(self.viewAnimator.fractionComplete)
if self.animatingBackwards {
value = 1 - value
}
self.animationSlider.value = value
}
}
else {
self.timer?.invalidate()
}
}
Я должен, вероятно, преобразовать код выше, чтобы использовать таймер CADisplayLink
вместо ванильного таймера (NSTimer), но я надеюсь, что там будет лучший способ.