Есть ли способ наблюдать изменения фракции в UIViewPropertyAnimator
Я смотрел на очень крутой новый 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
"s 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), но я надеюсь, что есть лучший способ.
2 ответа
К вашему сведению, после изучения этого ответа, кажется, что нет, нет никакого способа получать обновления по мере продвижения вашей анимации. Вы должны установить таймер (либо
Вы пытались создать подкласс UIViewPropertyAnimator, а затем переопределить свойство fractionComplete?
class MyPropertyAnimator : UIViewPropertyAnimator {
override var fractionComplete: CGFloat {
didSet {
print("didSetFraction")
}
}
}