解決Viewcontroller 做爲modal視圖彈出時沒法半透明,和底層view變黑的問題

主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

UIViewController Initializers in Swift

相關文章
相關標籤/搜索