Swift基礎之自定義PUSH和POP跳轉動畫
之前用OC程式碼寫過PUSH和POP的轉場動畫,閒來無事,將其轉換成Swift語言,希望對大家有幫助,轉載請註明。。。。
如何實現PUSH和POP的轉場動畫?
首先,建立一個NSObject的類,分別用來實現PUSH和POP的動畫效果
建立PUSH檔案,實現扇形效果,程式碼如下:
需要注意的是,代理的實現方法要完整
var transitionContextT:UIViewControllerContextTransitioning?
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.8
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
self.transitionContextT = transitionContext
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
//不新增的話,螢幕什麼都沒有
let containerView = transitionContext.containerView
containerView.addSubview((fromVC?.view)!)
containerView.addSubview((toVC?.view)!)
let originRect:CGRect = CGRect.init(x: 0, y: 0, width: 50, height: 50)
let maskStartPath = UIBezierPath.init(ovalIn: originRect)
//OC中CGRectInset(originRect, -2000, -2000)的Swift用法:originRect.insetBy(dx: -2000, dy: -2000)
let maskEndPath = UIBezierPath.init(ovalIn: originRect.insetBy(dx: -2000, dy: -2000))
//建立一個CAShapeLayer來負責展示圓形遮蓋
let maskLayer = CAShapeLayer.init()
//將他的path指定為最終的path,來避免在動畫完成後回彈
maskLayer.path = maskEndPath.cgPath
toVC?.view.layer.mask = maskLayer
let maskAnimation = CABasicAnimation.init(keyPath: "path")
maskAnimation.fromValue = maskStartPath.cgPath
maskAnimation.toValue = maskEndPath.cgPath
maskAnimation.duration = self.transitionDuration(using: transitionContext)
maskAnimation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
maskAnimation.fillMode = kCAFillModeForwards
maskAnimation.isRemovedOnCompletion = false
maskAnimation.delegate = self
maskLayer.add(maskAnimation, forKey: "path")
}
//MARK:----- CAAnimationDelegate
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.transitionContextT?.completeTransition(!(self.transitionContextT?.transitionWasCancelled)!)
//去除mask
self.transitionContextT?.viewController(forKey: UITransitionContextViewControllerKey.from)?.view.layer.mask = nil;
self.transitionContextT?.viewController(forKey: UITransitionContextViewControllerKey.to)?.view.layer.mask = nil;
}
然後,同理建立POP檔案,實現彈跳的效果,程式碼如下:
var transitionContext:UIViewControllerContextTransitioning?
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.8
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
//不新增的話,螢幕什麼都沒有
let containerView = transitionContext.containerView
containerView.addSubview((fromVC?.view)!)
containerView.addSubview((toVC?.view)!)
let durationN = self.transitionDuration(using: transitionContext)
let screenBounds:CGRect = UIScreen.main.bounds
let finalFrame:CGRect = transitionContext.finalFrame(for: toVC!)
//OC中CGRectOffset(finalFrame, 0, -screenBounds.size.height)的Swift的用法:finalFrame.offsetBy(dx: 0, dy: -screenBounds.size.height)
toVC?.view.frame = finalFrame.offsetBy(dx: 0, dy: -screenBounds.size.height)
//新增動畫,有彈跳的效果,引數:usingSpringWithDamping的範圍為0.0f到1.0f,數值越小「彈簧」的振動效果越明顯,當設定為1.0時,就不彈跳
//toVC?.view.frame = finalFrame
//transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
UIView.animate(withDuration: durationN, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.0, options: UIViewAnimationOptions.curveLinear, animations: {() -> Void in
//print("11111111")
toVC?.view.frame = finalFrame
}, completion: ({(Bool) -> Void in
//print("22222222")
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}))
}
最後在需要使用跳轉動畫的地方新增self.navigationController?.delegate = self代理方法,並實現,程式碼如下:
//MARK:-----UINavigationControllerDelegate
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if operation==UINavigationControllerOperation.push {
return BHPopAnimation()
}
else if operation==UINavigationControllerOperation.pop{
return BHPushAnimation()
}
return nil
}