2015-05-24 2 views
0

Я пишу сложную анимацию немного, которая идет в 2 этапа:CATransaction: взгляд вспыхивает на завершение

  1. Изменение непрозрачности до 0 из UIViews, которые не должны быть видны и переместить UIImageView (который имеет alpha = 1) другому CGPoint (позиция).
  2. Изменить непрозрачность другого UIView на 1 и непрозрачность UIImageView с предыдущего шага на 0, а затем после того, как анимация этого этапа будет завершена, удалите 0BCиз супервизора.

Я сделал это так:

первый шаг делается без явного 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.

Ну, вопрос в том, как избавиться от этого проблескивания? Может быть, эта анимация может быть выполнена лучше?

P.S. Я не использую анимацию UIView, потому что меня интересуют пользовательские функции синхронизации для этих анимаций.

EDIT 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() 

EDIT 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), но это не помогло.

EDIT 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() 
+0

Пожалуйста, покажите свой код, или достаточно похожий/уменьшенный код, чтобы сделать проблему легко воспроизвести. – matt

+0

Добавлен код. – Randex

+0

Ну, что это за вспышка? Можем ли мы исключить код для других анимаций? – matt

ответ

1

Просто глядя на свой код, я бы ожидать его прошить. Зачем? Потому что вы оживили непрозрачность timeView «S слоя от 0 до 1, но вы не установить его к 1 (за исключением обработчика завершения, который будет позже). Таким образом, мы анимируем слой представления от 0 до 1, а затем анимация заканчивается, и выясняется, что непрозрачность реального слоя была равна 0.

Итак, установите непрозрачность timeView «s слоя 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 для каждой анимации, если бы я был вами.

+0

Спасибо! Но почему вы не можете рекомендовать повторное использование CABasicAnimations? – Randex

+0

'пусть длительность = 0.3' - да, я забыл вставить эту строку, когда я редактировал вопрос:' alphaAnimation.duration = duration' – Randex

+0

«Но почему вы не можете рекомендовать повторное использование CABasicAnimations» Это только кажется ленивым и ненужным. Плюс это немного рискованно. Случается, что CABasicAnimation копируется, когда ему назначается слой, поэтому ваши последующие изменения не влияют на ранее назначенные анимации, но это всего лишь деталь реализации. В общем случае экземпляр класса следует рассматривать как экземпляр класса - он изменен, а мутации влияют на все ссылки на него. – matt

Смежные вопросы