Swift ViewControllerTransitions

自定义Modally转场动画

准备

delegate转交给viewcontroller而不是系统

vc.transitioningDelegate = self

遵循协议

extension MainViewController:UIViewControllerTransitioningDelegate {
    
    //出现的函数,返回一个UIViewControllerAnimatedTransitioning的一个动画器,于是就新建一个
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return PresentAnimator()
    }
    //退出的函数,同上返回一个动画器
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return DismissAnimator()
    }
}

两个动画器

创建动画器

在这里插入图片描述

遵循两个协议

完成两个固定方法,一个设置动画经过时间,一个设置动画逻辑

class PresentAnimator:NSObject, UIViewControllerAnimatedTransitioning {

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {}
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {}
}

完成动画器

PresentAnimator:

class PresentAnimator:NSObject, UIViewControllerAnimatedTransitioning {
    
    //动画的经过时间
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }
    
    //动画逻辑
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        
        guard
            //转场开始的vc
//            let fromVC = transitionContext.viewController(forKey: .from),
            //转场开始vc的根视图
            let fromView = transitionContext.view(forKey: .from),
            
            //转场结束的vc
//            let toVC = transitionContext.viewController(forKey: .to),
            //转场结束的vc的根视图
            let toView = transitionContext.view(forKey: .to)
        else{return}
        
        //类似于NavigationView
        let containerView = transitionContext.containerView
        //加入toView,UIKit会自动加入fromView
        containerView.addSubview(toView)
        
        toView.alpha = 0
        toView.transform = CGAffineTransform(translationX: containerView.frame.width, y: 0)
        
        UIView.animate(
            withDuration: transitionDuration(using: transitionContext),
            animations: {
                fromView.alpha = 0
                fromView.transform = CGAffineTransform(translationX: -containerView.frame.width, y: 0)
                toView.alpha = 1
                toView.transform = .identity
        }) { _ in
            fromView.transform = .identity
            toView.transform = .identity
            
            //UIKit调用这个方法来结束转场动画
            transitionContext.completeTransition(true)
        }
        
    }
    
//tcontainerView在动画结束的时候会自动移除fromView只剩下toView,一旦toView被dismiss就会黑屏,但是fromView的transform属性还在,所以在最后要给他还原
}


DismissAnimator:

class DismissAnimator: NSObject,UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        
        guard
            let fromView = transitionContext.view(forKey: .from),
            let toView = transitionContext.view(forKey: .to)
        else{return}
        
        let containerView = transitionContext.containerView
        
        containerView.addSubview(toView)
        
        toView.alpha = 0
        toView.transform = CGAffineTransform(translationX: -containerView.frame.width, y: 0)
        
        UIView.animate(
            withDuration: transitionDuration(using: transitionContext),
            animations: {
                
                toView.alpha = 1
                toView.transform = .identity
                
                fromView.alpha = 0
                fromView.transform = CGAffineTransform(translationX: containerView.frame.width, y: 0)
        }) { _ in
            fromView.transform = .identity
            toView.transform = .identity
            
            transitionContext.completeTransition(true)
        }
        
    }
    

}


在转到的VC上设置dismiss

在ImageView上添加手势记得要加上
在这里插入图片描述

class DetailViewController: UIViewController {

    
    @IBOutlet weak var detailImageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //target表示这个手势在哪里运行,actiont传入函数的固定写法
        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(tap:)))
        detailImageView.addGestureRecognizer(tap)
        // Do any additional setup after loading the view.
    }
    

    @objc func handleTap(tap:UITapGestureRecognizer) {
        dismiss(animated: true, completion: nil)
    }

}

发布了19 篇原创文章 · 获赞 8 · 访问量 1223

猜你喜欢

转载自blog.csdn.net/qq_44864362/article/details/104229084