美文网首页
swift 给一个modal出来的控制器设置转场动画【转载XMG

swift 给一个modal出来的控制器设置转场动画【转载XMG

作者: 陈水寒 | 来源:发表于2017-08-31 09:57 被阅读38次

    1. 设置控制器属性

            // 设置modal样式,弹出后原来的view不会消失,默认modal出来的控制器view会将原来的view移除
            popoverVc.modalPresentationStyle = .custom
            // 设置转场代理
            popoverVc.transitioningDelegate = self
    

    2. 设置转场代理方法

    // MARK:- transitioningDelegate代理
    extension GGHomeViewController : UIViewControllerTransitioningDelegate {
        /// 目的:改变弹出view的frame,需要自定义UIPresentationController
        func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
            return GGPresentationController(presentedViewController: presented, presenting: presenting)
        }
        
        /// 目的:设置弹出动画
        func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            isPresented = true // 由于弹出和消失用的是同一个协议,所需需要设置一个标志位来区分是弹出还是消失
            return self
        }
        /// 目的:设置消失动画
        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            isPresented = false
            return self
        }
    }
    
    2.1 自定义UIPresentationController
    class GGPresentationController: UIPresentationController {
        
        // MARK:- 懒加载属性
        fileprivate lazy var coverView : UIView = UIView()
        
        // MARK:- 系统函数回调
        override func containerViewWillLayoutSubviews() {
            super.containerViewWillLayoutSubviews()
            
            // 设置frame
            presentedView?.frame = CGRect(x: 100, y: 55, width: 180, height: 250)
            
            setupCoverView()
        }
    }
    
    // MARK:- 设置蒙版
    extension GGPresentationController {
        fileprivate func setupCoverView() {
            // 1. 添加蒙版
            containerView?.insertSubview(coverView, at: 0)
            
            // 2. 设置属性
            coverView.frame = containerView!.bounds
            coverView.backgroundColor = UIColor(white: 0.6, alpha: 0.2)
            
            // 3. 给蒙版添加手势事件
            let tabGes = UITapGestureRecognizer(target: self, action: #selector(GGPresentationController.coverViewTapGesClk))
            coverView.addGestureRecognizer(tabGes)
        }
    }
    
    // MARK:- 手势点击处理
    extension GGPresentationController {
        @objc fileprivate func coverViewTapGesClk() {
            print("coverViewTapGesClk")
            presentedViewController.dismiss(animated: true, completion: nil)
        }
    }
    

    3. 设置弹出、消失动画的协议

    // MARK:- UIViewControllerAnimatedTransitioning协议
    extension GGHomeViewController : UIViewControllerAnimatedTransitioning {
        /// 设置动画播放事件
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.5
        }
        
        /// 设置动画效果
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            isPresented ? animationToPresentedView(using: transitionContext) : animationToDismissedView(using: transitionContext)
        }
        
        // 弹出动画
        fileprivate func animationToPresentedView(using transitionContext: UIViewControllerContextTransitioning) {
            // 1. 获取弹出的view
            let presentedView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
            
            // 2. 添加view
            transitionContext.containerView.addSubview(presentedView)
            
            // 3. 设置动画
            presentedView.transform = CGAffineTransform(scaleX: 1.0, y: 0.0)
            presentedView.layer.anchorPoint = CGPoint(x: 0.5, y: 0) // 动画的开始位置
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                presentedView.transform = CGAffineTransform.identity
            }) { (_) in
                // 4. 完成动画
                transitionContext.completeTransition(true)
            }
        }
        
        // 消失动画
        // 返回的对象是一个协议,直接设置成当前对象
        fileprivate func animationToDismissedView(using transitionContext: UIViewControllerContextTransitioning) {
            // 1. 获取弹出的view
            let presentedView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
            
            // 2. 设置动画
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                presentedView.transform = CGAffineTransform(scaleX: 1.0, y: 0.001)
            }) { (_) in
                // 3. 完成动画
                transitionContext.completeTransition(true)
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:swift 给一个modal出来的控制器设置转场动画【转载XMG

          本文链接:https://www.haomeiwen.com/subject/gbifjxtx.html