0

我正在编写一个有点复杂的动画,它分为两个步骤:

  1. 将不透明度更改为 0UIViews不需要可见并将 a UIImageView(具有alpha = 1)移动到另一个CGPoint(位置)。
  2. 将另一个UIView的不透明度改为1,UIImageView将上一步的不透明度改为0,然后在这一步的动画完成后,UIImageView从superview中移除。

我是这样做的:

第一步是在没有显式 CATransaction 的情况下完成的。这 2 个动画刚刚beginTime设置为CACurrentMediaTime(). 我在layer.addAnimation(...)通话后立即对视图应用更改。这里一切正常。

第二步实施中,我CATransaction.begin()一开始就打电话。内部begin/commit调用CATransaction我创建并添加 2CABasicAnimations到 2 个不同的层:一个用于将不透明度从 0 更改为 1(用于UIView),一个用于将不透明度从 1 更改为 0(用于UIImageView)。两个动画都beginTime设置为CACurrentMediaTime() + durationOfThePreviousStep

CATransaction.begin()我调用之后CATransaction.setCompletionBlock({...}),在这个完成块中,我对这两个视图应用更改:设置它们的新 alpha 并UIImageView从超级视图中删除。

问题是,在整个动画结束时UIView,alpha 动画为 1 次闪烁,这意味着它的 alpha 设置回 0(尽管我在完成块中将其 alpha 设置为 1),并且在完成块之后执行并且它的 alpha 再次上升到 1。

那么,问题是,如何摆脱这种闪烁?也许这个动画可以以更好的方式完成?

PS 我没有使用UIView动画,因为我对这些动画的自定义计时功能感兴趣。

编辑1:这是代码。我已经删除UIImageView了 alpha 动画,因为它不是真的必要。

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的快照替换,但这没有帮助。timeViewUIImageView

编辑 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()
4

1 回答 1

4

只看你的代码,我希望它会闪烁。为什么?因为您已将动画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。

于 2015-05-24T15:33:29.620 回答