美文网首页
自定义转场动画进阶

自定义转场动画进阶

作者: 纳兰沫 | 来源:发表于2019-11-19 10:19 被阅读0次

    交互动画的优先级比 不交互动画高

    //交互动画 主要是手势动画
        func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    
            return PanInteraction(detailView: ViewController())
        }
        
        func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
            return nil
        }
    
    class PanInteraction: UIPercentDrivenInteractiveTransition {
    
        let detailVC: UIViewController
        init(detailView: ViewController) {
            
            self.detailVC = detailView
            super.init()
            let pan  = UIPanGestureRecognizer(target: self, action: #selector(handlePan(pan:)))
            detailView.view.addGestureRecognizer(pan)
        }
        
        @objc func handlePan(pan: UIPanGestureRecognizer ){
            
            let progress = pan.translation(in: pan.view).x / UIScreen.main.bounds.width
            switch pan.state {
            case .began:
                detailVC.dismiss(animated: true, completion: nil)
            case .changed:
                 update(progress)
            case .cancelled,.ended:
                if progress > 0.5 {
                    finish()
                }else{
                    cancel()
                }
            default: break
                
            }
        }
    }
    

    UINavigation 自定义动画

    extension MainViewController: UINavigationControllerDelegate {
        
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            
            if let _ = segue.destination as? ViewController {
                panInteraction = PanAnimation(detailVC: ViewController())
            }
        }
        
        func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?{
            guard let panInteraction = panInteraction else {
                return nil
            }
            return panInteraction
        }
        
        
        func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?{
            
            switch operation {
            case .push:
                return PushAnimator()
            case .pop:
                return PopAnimator()
            default:
                return nil
            }
        }
    }
    
    class PushAnimator: NSObject,UIViewControllerAnimatedTransitioning {
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.3
        }
        
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            
            let containerView = transitionContext.containerView
            guard let fromVC = transitionContext.viewController(forKey: .from),
                let toVC = transitionContext.viewController(forKey: .to),
                let fromView = transitionContext.view(forKey: .from),
                let toView = transitionContext.view(forKey: .to) else{ return }
            
            containerView.addSubview(toView)
            toView.transform = CGAffineTransform(translationX: containerView.frame.width, y: 0)
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    
                    fromView.transform = CGAffineTransform(translationX: -containerView.frame.width, y: 0)
                    fromView.alpha = 0
                    toView.alpha = 1
                    toView.transform = .identity
            }) { _ in
                
                fromView.transform = .identity
                toView.transform = .identity
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            }
        }
        
    
    }
    
    class PopAnimator: NSObject,UIViewControllerAnimatedTransitioning {
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.3
        }
        
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            
            let containerView = transitionContext.containerView
            guard let fromVC = transitionContext.viewController(forKey: .from),
                let toVC = transitionContext.viewController(forKey: .to),
                let fromView = transitionContext.view(forKey: .from),
                let toView = transitionContext.view(forKey: .to) else{ return }
            
            containerView.insertSubview(toView, belowSubview: fromView)
            
            //和shadowPath一样 视图虽然被移除了 但是 属性仍在 所以直接设为原来状态
            toView.alpha = 1
            toView.transform = CGAffineTransform(translationX: -containerView.frame.width/3, y: 0)
            //除shadowOpacity都有默认值 实现简单阴影只要给shadowOpacity就可以
            fromView.layer.shadowOpacity = 0.5
            fromView.layer.shadowRadius = 10
            //若指定shadowPath 系统会自动帮我们找到对应的view 渲染阴影
            fromView.layer.shadowPath = UIBezierPath(rect: fromView.bounds).cgPath
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    
                    fromView.transform = CGAffineTransform(translationX: containerView.frame.width, y: 0)
                    toView.transform = .identity
            }) { _ in
                fromView.transform = .identity
                toView.transform = .identity
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            }
        }
    }
    

    Tabbar自定义动画

    import UIKit
    
    enum Operation {
        case toRight,toLeft
    }
    
    class TabBarViewController: UITabBarController {
    
        var customInteraction: CustomInteraction!
        override func viewDidLoad() {
            super.viewDidLoad()
            
            customInteraction = CustomInteraction(tabBarVC: self)
            self.delegate = self
        }
      
    }
    
    extension TabBarViewController: UITabBarControllerDelegate {
        
        //非交互动画
        func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            
            let fromIndex = tabBarController.viewControllers!.firstIndex(of: fromVC)!
            let toIndex = tabBarController.viewControllers!.firstIndex(of: toVC)!
            let operation: Operation = toIndex > fromIndex ? .toRight : .toLeft
            return CustomAnimator(operation: operation)
        }
        
        //交互动画
        func tabBarController(_ tabBarController: UITabBarController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
            return customInteraction.isInteractive ? customInteraction : nil
        }
        
       
    }
    
    非交互动画
    import UIKit
    
    class CustomAnimator: NSObject,UIViewControllerAnimatedTransitioning {
        
        let operation: Operation
        init(operation: Operation) {
            self.operation = operation
            super.init()
        }
        
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.3
        }
        
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            
            let containerView = transitionContext.containerView
            guard let fromView = transitionContext.view(forKey: .from),
                 let toView = transitionContext.view(forKey: .to) else {
                return
            }
            containerView.addSubview(toView)
            
            let offset = containerView.frame.width
            toView.frame.origin.x = (operation == .toRight) ? offset : -offset
            toView.alpha = 0
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    
                    fromView.alpha = 0
                    let offset = containerView.frame.width
                    fromView.frame.origin.x = (self.operation == .toRight) ? -offset : offset
                    
                    toView.alpha = 1
                    toView.frame.origin.x = 0
                    
            }) { _ in
                
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            }
        }
        
    
    }
    
    交互动画
    import UIKit
    
    class CustomInteraction: UIPercentDrivenInteractiveTransition {
    
        var isInteractive = false
        let tabBarVC: TabBarViewController
        init(tabBarVC: TabBarViewController) {
            
            self.tabBarVC = tabBarVC
            super.init()
            let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(pan:)))
            tabBarVC.view.addGestureRecognizer(pan)
        }
        
        @objc func handlePan(pan: UIPanGestureRecognizer){
            
            let translationX = pan.translation(in: pan.view).x
            let progress = abs(translationX / 200)
            switch pan.state {
            case .began:
                isInteractive = true
                //translationX 小于0 是用户向左滑 大于0 是向右滑
                if translationX < 0 {
                    if tabBarVC.selectedIndex <= tabBarVC.viewControllers!.count - 2 {
                        tabBarVC.selectedIndex += 1
                    }
                }else{
                    if tabBarVC.selectedIndex >= 1 {
                        tabBarVC.selectedIndex -= 1
                    }
                }
            case .changed:
                update(progress)
            case .cancelled,.ended:
                isInteractive = false
                if progress > 0.5 {
                    finish()
                }else{
                    cancel()
                }
            default:
                break
            }
            
        }
    }
    

    相关文章

      网友评论

          本文标题:自定义转场动画进阶

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