主Viewcontroller 須要使用UIViewControllerTransitioningDelegate協議:swift
class ViewController: UIViewController ,UIViewControllerTransitioningDelegate{ var customAnimationController:BouncePresentAnimation var dismiassAni : NormalDismissAnimation required init(coder aDecoder: NSCoder) { customAnimationController = BouncePresentAnimation() dismiassAni = NormalDismissAnimation() super.init(coder: aDecoder) } func animationControllerForPresentedController(presented: UIViewController!, presentingController presenting: UIViewController!, sourceController source: UIViewController!) -> UIViewControllerAnimatedTransitioning! { return self.customAnimationController } func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return self.dismiassAni } }
此時涉及到利用coder aDecoder: NSCoder初始化,因此其餘地方如何引用這個viewcontroller也是個難題: iview
let loginVc = UINavigationController(rootViewController: ViewController(coder: NSCoder.empty())) extension NSCoder { class func empty() -> NSCoder { let data = NSMutableData() let archiver = NSKeyedArchiver(forWritingWithMutableData: data) archiver.finishEncoding() return NSKeyedUnarchiver(forReadingWithData: data) } }
彈出modal類,主要應用了動畫:函數
class BouncePresentAnimation: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { return 0.8 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { // 1. Get controllers from transition context let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) // 2. Set init frame for toVC let finalFrame = transitionContext.finalFrameForViewController(toViewController!) let containerView = transitionContext.containerView() let realFrame = CGRectMake(finalFrame.origin.x+300, finalFrame.origin.y, finalFrame.width, finalFrame.height) //finalFrame.origin.x = finalFrame.origin.x + 100 let screenBounds = UIScreen.mainScreen().bounds toViewController?.view.frame = CGRectOffset(finalFrame,screenBounds.size.width,0) // 3. Add toVC's view to containerView let toView = toViewController!.view //toView.opaque = true //toView.alpha = 0.8 containerView.addSubview(toView) //動畫 let duration = self.transitionDuration(transitionContext) UIView.animateWithDuration(duration, // 動畫時長 delay : 0, usingSpringWithDamping : 0.8, // 相似彈簧振動效果 0~1 initialSpringVelocity : 0.2, // 初始速度 options : .CurveLinear, // 動畫過渡效果 animations: { toViewController!.view.frame = finalFrame }, completion: {(Bool finished) in transitionContext.completeTransition(true) }) } }
接下來是關閉的效果:測試
class NormalDismissAnimation: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { return 0.4 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { // 1. Get controllers from transition context let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) // 2. Set init frame for toVC let screenBounds = UIScreen.mainScreen().bounds let initFrame = transitionContext.finalFrameForViewController(fromViewController!) let finalFrame = CGRectOffset(initFrame, screenBounds.size.width, 0); let containerView = transitionContext.containerView() // 3. Add toVC's view to containerView containerView.addSubview(toViewController!.view) containerView.sendSubviewToBack(toViewController!.view) //動畫 let duration = self.transitionDuration(transitionContext) UIView.animateWithDuration(duration, animations: { fromViewController!.view.frame = finalFrame }, completion: {(Bool finished) in transitionContext.completeTransition(!transitionContext.transitionWasCancelled()) if let window = UIApplication.sharedApplication().keyWindow { if let viewController = window.rootViewController { window.addSubview(toViewController!.view) } } }) } }
主view中調用彈出函數:動畫
func goModal(){ var mVC = modalViewController() mVC.transitioningDelegate = self mVC.view.backgroundColor = UIColor.clearColor() mVC.modalPresentationStyle = .Custom self.presentViewController(mVC, animated: true, completion: nil) }
這裏須要注意設置 mVC.view.backgroundColor = UIColor.clearColor() 後才能夠在modal層中實現半透明.ui
還有一點是有個IOS8的bug,當彈出層收回時,主view會是黑屏.這裏在DismissAnimation中,當completion: {(Bool finished) in 時 ,須要將toViewController.view加入到window中.spa
本例針對IOS8 版本測試code
引用地址:orm