UIView 自定义过渡在完成时快速返回
UIView custom transition snaps back on completion
我已经实现了 class BubbleAnimator
,它应该在视图之间创建类似气泡的过渡,并通过 UIViewControllerTransitioningDelegate
-协议添加它。演示动画到目前为止工作正常(这就是我没有为这部分添加所有代码的原因)。
但是在关闭视图时,'fromViewController' 在动画的最后闪烁 。在这个非常短的闪烁之后,正确的 toViewController
再次显示,但是这个故障非常烦人。
以下是相关的animateTransition
-方法:
//Get all the necessary views from the context
let containerView = transitionContext.containerView()
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
//Presenting
if self.reverse == false {
//Add the destinationvc as subview
containerView!.addSubview(fromViewController!.view)
containerView!.addSubview(toViewController!.view)
/*...Animating the layer goes here... */
//Dismissing
} else {
containerView!.addSubview(toViewController!.view)
containerView!.addSubview(fromViewController!.view)
//Init the paths
let circleMaskPathInitial = UIBezierPath(ovalInRect: self.originFrame)
let extremePoint = CGPoint(x: originFrame.origin.x , y: originFrame.origin.y - CGRectGetHeight(toViewController!.view.bounds) )
let radius = sqrt((extremePoint.x*extremePoint.x) + (extremePoint.y*extremePoint.y))
let circleMaskPathFinal = UIBezierPath(ovalInRect: CGRectInset(originFrame, -radius, -radius))
//Create a layer
let maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
fromViewController!.view.layer.mask = maskLayer
//Create and add the animation
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = circleMaskPathInitial.CGPath
animation.fromValue = circleMaskPathFinal.CGPath
animation.duration = self.transitionDuration(transitionContext)
animation.delegate = self
maskLayer.addAnimation(animation, forKey: "path")
}
清理发生在委托方法中:
override public func animationDidStop(anim: CAAnimation, finished flag: Bool) {
self.transitionContext?.completeTransition(!(self.transitionContext?.transitionWasCancelled())!)
}
我想,我在将视图添加到 containerView 时做错了什么,但我无法弄清楚。另一种可能性是,当函数 completeTransition
被调用时,视图的图层蒙版被重置。
感谢this blogpost,我终于能够解决这个问题。简短说明:
CAAnimation只操作视图的表现层,不改变模型层。当动画现在结束时,它的值会恢复到模型层的原始值和未更改的值。
简短而简单的解决方法:
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
更好的解决方案是在动画开始之前手动设置图层位置的最终值,因为它不会阻止动画被删除。这样,模型层就被赋予了正确的值:
maskLayer.path = circleMaskPathInitial.CGPath
//Create and add the animation below..
我已经实现了 class BubbleAnimator
,它应该在视图之间创建类似气泡的过渡,并通过 UIViewControllerTransitioningDelegate
-协议添加它。演示动画到目前为止工作正常(这就是我没有为这部分添加所有代码的原因)。
但是在关闭视图时,'fromViewController' 在动画的最后闪烁 。在这个非常短的闪烁之后,正确的 toViewController
再次显示,但是这个故障非常烦人。
以下是相关的animateTransition
-方法:
//Get all the necessary views from the context
let containerView = transitionContext.containerView()
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
//Presenting
if self.reverse == false {
//Add the destinationvc as subview
containerView!.addSubview(fromViewController!.view)
containerView!.addSubview(toViewController!.view)
/*...Animating the layer goes here... */
//Dismissing
} else {
containerView!.addSubview(toViewController!.view)
containerView!.addSubview(fromViewController!.view)
//Init the paths
let circleMaskPathInitial = UIBezierPath(ovalInRect: self.originFrame)
let extremePoint = CGPoint(x: originFrame.origin.x , y: originFrame.origin.y - CGRectGetHeight(toViewController!.view.bounds) )
let radius = sqrt((extremePoint.x*extremePoint.x) + (extremePoint.y*extremePoint.y))
let circleMaskPathFinal = UIBezierPath(ovalInRect: CGRectInset(originFrame, -radius, -radius))
//Create a layer
let maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
fromViewController!.view.layer.mask = maskLayer
//Create and add the animation
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = circleMaskPathInitial.CGPath
animation.fromValue = circleMaskPathFinal.CGPath
animation.duration = self.transitionDuration(transitionContext)
animation.delegate = self
maskLayer.addAnimation(animation, forKey: "path")
}
清理发生在委托方法中:
override public func animationDidStop(anim: CAAnimation, finished flag: Bool) {
self.transitionContext?.completeTransition(!(self.transitionContext?.transitionWasCancelled())!)
}
我想,我在将视图添加到 containerView 时做错了什么,但我无法弄清楚。另一种可能性是,当函数 completeTransition
被调用时,视图的图层蒙版被重置。
感谢this blogpost,我终于能够解决这个问题。简短说明:
CAAnimation只操作视图的表现层,不改变模型层。当动画现在结束时,它的值会恢复到模型层的原始值和未更改的值。
简短而简单的解决方法:
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
更好的解决方案是在动画开始之前手动设置图层位置的最终值,因为它不会阻止动画被删除。这样,模型层就被赋予了正确的值:
maskLayer.path = circleMaskPathInitial.CGPath
//Create and add the animation below..