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

2017-08-31  本文已影响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)
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读