CATransaction:视图在完成时闪烁

时间:2015-05-24 12:43:56

标签: ios uiview core-animation cabasicanimation catransaction

我正在编写一些复杂的动画,分为两步:

  1. 将不透明度更改为UIViews的0不需要显示,并将UIImageView(具有alpha = 1)移至另一个CGPoint(位置)。
  2. 将另一个UIView的不透明度更改为1,将UIImageView的不透明度从上一步更改为0,然后在完成此步骤的动画后,从超级视图中删除UIImageView
  3. 我已经这样做了:

    第一步是在没有明确的CATransaction的情况下完成的。这2个动画的beginTime设置为CACurrentMediaTime()。我在layer.addAnimation(...)电话后立即对视图进行了更改。 这里的一切都很好。

    第二步实施中,我在开头调用CATransaction.begin()。 在begin/commitCATransaction调用我创建2 CABasicAnimations并将其添加到2个不同的图层:一个用于将不透明度从0更改为1(用于UIView),另一个用于更改不透明度从1到0(对于UIImageView)。两种动画都将beginTime设置为CACurrentMediaTime() + durationOfThePreviousStep

    CATransaction.begin()之后我立即致电CATransaction.setCompletionBlock({...}),在此完成版块中,我对这两个视图应用了更改:设置新的alpha并从superview中删除UIImageView

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

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

    P.S。我没有使用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()
    

    问题可能是因为timeViewUITextFieldUIScrollView有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()
    

1 个答案:

答案 0 :(得分:2)

只要看看你的代码,我就期待它闪存。为什么?因为你将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。