自定义转场动画进阶

2019-11-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
        }
        
    }
}
上一篇 下一篇

猜你喜欢

热点阅读