CATransaction: по завершении мигает вид
Я пишу немного сложную анимацию, которая состоит из 2 шагов:
- Изменить непрозрачность до 0 из
UIViews
которые не должны быть видны и перемещатьUIImageView
(у которого естьalpha = 1
) другомуCGPoint
(позиция). - Изменить непрозрачность другого
UIView
1 и непрозрачностьUIImageView
от предыдущего шага до 0, а затем после завершения анимации этого шага удалитеUIImageView
из супервизии.
Я сделал это так:
Первый шаг выполняется без явной CATransaction. Эти 2 анимации просто имеют beginTime
установлен в CACurrentMediaTime()
, И я применяю изменения к представлениям сразу после layer.addAnimation(...)
вызов. Здесь все отлично работает.
На втором этапе реализации я называю CATransaction.begin()
в начале. внутри begin/commit
звонки в CATransaction
Я создаю и добавляю 2 CABasicAnimations
до 2 разных слоев: один для изменения непрозрачности от 0 до 1 (для UIView
) и один для изменения непрозрачности от 1 до 0 (для UIImageView
). Обе анимации имеют beginTime
установлен в CACurrentMediaTime() + durationOfThePreviousStep
,
И сразу после CATransaction.begin()
Я звоню CATransaction.setCompletionBlock({...})
и в этом блоке завершения я применяю изменения к этим двум представлениям: установите их новые альфа и удалите UIImageView
из супервизии.
Проблема в том, что в конце всей этой анимации UIView
у него альфа-анимация мигает до 1, что означает, что его альфа возвращается в 0 (хотя я установил альфа в 1 в блоке завершения), и сразу после этого выполняется блок завершения, и его альфа снова увеличивается до 1.
Ну, вопрос, как избавиться от этой перепрошивки? Может быть, эту анимацию можно сделать лучше?
PS я не пользуюсь UIView
анимации, потому что я заинтересован в пользовательских функциях синхронизации для этих анимаций.
РЕДАКТИРОВАТЬ 1: Вот код. Я удалил UIImageView
альфа-анимация, потому что это на самом деле не нужно.
var totalDuration: CFTimeInterval = 0.0
// Alpha animations.
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 1
alphaAnimation.toValue = 0
alphaAnimation.beginTime = CACurrentMediaTime()
alphaAnimation.duration = 0.15
let alphaAnimationName = "viewsFadeOut"
view1.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view1.alpha = 0
view2.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view2.alpha = 0
view3.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view3.alpha = 0
view4.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view4.alpha = 0
// Image View moving animation.
// Add to total duration.
let rect = /* getting rect */
let newImagePosition = view.convertPoint(CGPoint(x: CGRectGetMidX(rect), y: CGRectGetMidY(rect)), fromView: timeView)
let imageAnimation = CABasicAnimation()
imageAnimation.keyPath = "position"
imageAnimation.fromValue = NSValue(CGPoint: imageView!.layer.position)
imageAnimation.toValue = NSValue(CGPoint: newImagePosition)
imageAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
imageAnimation.beginTime = CACurrentMediaTime()
imageAnimation.duration = 0.3
imageView!.layer.addAnimation(imageAnimation, forKey: "moveImage")
imageView!.center = newImagePosition
totalDuration += imageAnimation.duration
// Time View alpha.
CATransaction.begin()
CATransaction.setCompletionBlock {
self.timeView.alpha = 1
self.imageView!.removeFromSuperview()
self.imageView = nil
}
let beginTime = CACurrentMediaTime() + totalDuration
let duration = 0.3
alphaAnimation.fromValue = 0
alphaAnimation.toValue = 1
alphaAnimation.beginTime = beginTime
alphaAnimation.duration = duration
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
/* imageView alpha animation is not necessary, so I removed it */
CATransaction.commit()
РЕДАКТИРОВАТЬ 2: кусок кода, который вызывает проблему:
CATransaction.begin()
CATransaction.setCompletionBlock {
self.timeView.alpha = 1
}
let duration = 0.3
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 0.0
alphaAnimation.toValue = 1.0
alphaAnimation.duration = duration
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
CATransaction.commit()
Может быть, проблема в том, что timeView
имеет UITextField
и UIScrollView
с 4 подпредставлениями. Я пытался заменить timeView
со снимком timeView
(UIImageView
), но это не помогло.
РЕДАКТИРОВАТЬ 3: Новый код. С этим кодом timeView
всегда имеет alpha = 1
, и это также оживляет от 0 до 1.
CATransaction.begin()
CATransaction.setCompletionBlock {
self.imageView!.removeFromSuperview()
self.imageView = nil
}
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 0.0
alphaAnimation.toValue = 1.0
alphaAnimation.duration = 0.3
alphaAnimation.beginTime = beginTime
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
timeView.alpha = 1.0
CATransaction.commit()
1 ответ
Просто глядя на ваш код, я ожидаю, что он будет мигать. Зачем? Потому что у вас есть анимация timeView
Непрозрачность слоя от 0 до 1, но вы не установили его на 1 (кроме обработчика завершения, что произойдет позже). Таким образом, мы анимируем уровень представления от 0 до 1, и затем анимация заканчивается, и обнаруживается, что непрозрачность реального слоя всегда была равна 0.
Итак, установите timeView
Непрозрачность слоя до 1 до начала анимации. Кроме того, так как вы используете задержанный beginTime
, вам нужно будет установить анимацию fillMode
в "backwards"
,
Я смог получить хорошие результаты, изменив свой тестовый код, чтобы он был автономным и выглядел следующим образом; есть задержка, вид исчезает, и в конце нет вспышки:
CATransaction.begin()
let beginTime = CACurrentMediaTime() + 1.0 // arbitrary, just testing
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 0.0
alphaAnimation.toValue = 1.0
alphaAnimation.duration = 1.0 // arbitrary, just testing
alphaAnimation.fillMode = "backwards"
alphaAnimation.beginTime = beginTime
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
timeView.layer.opacity = 1.0
CATransaction.commit()
Есть некоторые другие вещи в вашем коде, которые я нахожу довольно странными. Таким образом, использование блока завершения транзакции несколько рискованно; Я не понимаю, почему вы не даете свою анимацию делегату. Кроме того, вы используете повторно alphaAnimation
многократно; Я не могу рекомендовать это. Я бы создал новую CABasicAnimation для каждой анимации на вашем месте.