您的位置:首页 > 移动开发 > IOS开发

iOS pushViewController的自定义动画(圆形放大进入下个页面)

2016-10-25 17:15 423 查看
首先我们需要自己写一个Transition用来代替原先的push动画:

class PushTransition: NSObject, UIViewControllerAnimatedTransitioning, CAAnimationDelegate {

private var tContext: UIViewControllerContextTransitioning!

var button: UIButton!   //点击哪个按钮push进来的,需要保存一下,用于计算动画位置

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.5
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.tContext = transitionContext

if let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey),
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) {

let contView = transitionContext.containerView()

var baseFrame = self.button.frame
if baseFrame.size.width != baseFrame.size.height { // 这里是为了确定button的中心
let length = min(baseFrame.size.height, baseFrame.size.width)
baseFrame = CGRectMake(self.button.center.x-length/2, self.button.center.y-length/2, length, length)
}
let maskStartPath = UIBezierPath(ovalInRect: baseFrame)
contView.addSubview(fromVC.view)
contView.addSubview(toVC.view)

var finalPoint: CGPoint
let toVCSize = toVC.view.bounds.size

if button.frame.origin.x > toVCSize.width/2 {
if button.frame.origin.y < toVCSize.height/2 {
//第一象限
finalPoint = CGPointMake(button.center.x, button.center.y-CGRectGetMaxY(toVC.view.bounds)+30)
}else {
//第四象限
finalPoint = CGPointMake(button.center.x, button.center.y)
}
}else {
if button.frame.origin.y < toVCSize.height/2 {
//第二象限
finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - CGRectGetMaxY(toVC.view.bounds)+30)
}else {
//第三象限
finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y)
}
}
let radius = sqrt((finalPoint.x*finalPoint.x)+(finalPoint.y*finalPoint.y))
let maskFinalPath = UIBezierPath(ovalInRect: CGRectInset(baseFrame, -radius, -radius))

//创建一个 CAShapeLayer 来负责展示圆形遮盖
let maskLayer = CAShapeLayer()
maskLayer.path = maskFinalPath.CGPath
toVC.view.layer.mask = maskLayer

let maskLayerAnimation = CABasicAnimation(keyPath: "path")
maskLayerAnimation.fromValue = maskStartPath.CGPath
maskLayerAnimation.toValue = maskFinalPath.CGPath
maskLayerAnimation.duration = self.transitionDuration(transitionContext)
maskLayerAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
maskLayerAnimation.delegate = self
maskLayer.addAnimation(maskLayerAnimation, forKey: "pushPath")
}
}

//CAAnimationDelegate 动画结束后清除当前的mask
func animationDidStop(anim: CAAnimation, finished flag: Bool) {
self.tContext.completeTransition(!self.tContext.transitionWasCancelled())
self.tContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view.layer.mask = nil
self.tContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view.layer.mask = nil
}
}


写好之后就可以在navigationController的rootViewController里面调用了。

首先让rootViewController遵守UINavigationControllerDelegate协议,然后实现下面的协议

func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if operation == UINavigationControllerOperation.Push {
//这里需要判断一下哪些ViewController需要调用这个效果,这里为了简便没写。
let trans = PushTransition()
trans.button = UIButton(type: .Custom)
trans.button.frame = CGRectMake(self.touchLocation.x-5, self.touchLocation.y-5, 10, 10)
return trans
}else {
return nil
}
}

其中,self.touchLocation是我保存的一个点击位置,取的是点击button的中心位置

其实PopViewController也可以加收回的动画,具体实现方法在下一篇博客中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: