【iOS動畫】學(xué)習(xí)筆記第三彈(ViewController Transition Animation)

本文是筆者學(xué)習(xí)iOS動畫的一些小總結(jié),接第二彈;

ViewController Transition Animation

之前在第一彈第二彈中我們?yōu)槟硞€view或者layer的某個屬性做動畫, 移動,放縮,漸變等效果。此時我們利用之前的知識,可以通過UIKit提供的API來自定義VC之間的轉(zhuǎn)場動畫,例如Modal動畫,Push動畫,Pop動畫。

Modal 動畫

 present(modalVC, animated: true, completion: nil)

我們經(jīng)常會用上述方式顯示一個控制器,默認的效果是從下往上的一個動畫,但是系統(tǒng)允許我們進行自定義這個呈現(xiàn)的效果,步驟如下:

  1. 遵守UIViewControllerTransitioningDelegate協(xié)議
        let modalVC = ModalViewController()
        modalVC.transitioningDelegate = self
        present(modalVC, animated: true, completion: nil)
  1. 實現(xiàn)兩個協(xié)議的方法
extension ViewController: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return transition
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return transition
    }
}

這里如果返回nil,那么UIKit還是會用系統(tǒng)默認的動畫效果進行呈現(xiàn)。

  1. 實現(xiàn) UIViewControllerAnimatedTransitioning兩個方法
    第二步中返回的對象是遵守UIViewControllerAnimatedTransitioning協(xié)議的對象;該協(xié)議有兩個必須實現(xiàn)的方法:
    transitionDuration(using:): 告訴UIKit自定義的動畫的時間;
    animateTransition(using:): 實現(xiàn)你想要的動畫效果;

下面給出一個漸變的Modal和Dismiss動畫栗子:

 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return animationDuration
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let toView = transitionContext.view(forKey: .to)
        
        containerView.addSubview(toView!)
        toView?.alpha = 0.0
        
        UIView.animate(withDuration: animationDuration, animations: {
            toView?.alpha = 1.0
        }, completion: { _ in
            transitionContext.completeTransition(true)
        })
    }
屏幕快照 2017-10-13 10.21.27.png

transitionContext在實現(xiàn)動畫中非常重要,因為它提供了你需要做動畫的對象,以Modal為例,默認的控制器的view叫做fromView,modal出來的控制器的view叫做toView,fromView和toView都是放到containerView中顯示的,當(dāng)動畫結(jié)束后,fromView會從containerView中移除。

VCModalAnimationDemo只是簡單的一個效果,實際需要中,我們完全可以做出更加酷炫的轉(zhuǎn)場動畫。

Push/Pop 動畫

navigationController?.pushViewController(DetailViewController(), animated: true)

導(dǎo)航控制器進行Push操作的時候,默認的UIKit會提供一個從右往左的動畫,同樣的UIKit也允許我們進行自定義這個呈現(xiàn)效果,步驟如下:

  1. 遵守UINavigationControllerDelegate協(xié)議
 navigationController?.delegate = self
  1. 實現(xiàn)協(xié)議方法
 func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        transition.operation = operation
        return transition
    }

這里如果返回nil,那么UIKit還是會用系統(tǒng)默認的動畫效果進行呈現(xiàn)。

  1. 實現(xiàn) UIViewControllerAnimatedTransitioning兩個方法,這里其實和Modal動畫是一樣的,同樣的是協(xié)議中兩個必須要實現(xiàn)的方法。

下面給出一個Push時候進行放大圖形進行展示新控制器View的動畫,Pop時候進行放縮當(dāng)前View直到消失的動畫,效果如下圖:

屏幕快照 2017-10-13 14.31.16.png

屏幕快照 2017-10-13 14.27.25.png

完整的Demo下載地址VCPushPopAnimationDemo

ViewController Interactive Transition Animation

我們不但可以自定義控制器之間的轉(zhuǎn)場動畫,我們還可以通過添加手勢來控制轉(zhuǎn)場動畫,就像iOS7中新加的一個手勢返回控制器的效果,步驟如下:

  1. 實現(xiàn)UINavigationControllerDelegate協(xié)議方法
 func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return transition.transitionInProgress ? transition : nil
    }

默認返回nil則不能控制動畫;

上述代碼中返回的transition對象是UIPercentDrivenInteractiveTransition的子類,該類遵守了UIViewControllerInteractiveTransitioning協(xié)議,使用該類我們不需要進行每一幀每一幀的控制動畫,只需要傳入根據(jù)手勢移動的位移即可,該類會自動顯示。

 @objc func handlePanGesture(recognizer: UIPanGestureRecognizer) {
        let translation = recognizer.translation(in: recognizer.view?.superview) // nivigation's view
        var progress: CGFloat = abs(translation.x / 200.0)
        progress = min(max(progress, 0.01), 0.99)
        
        switch recognizer.state {
        case .began:
           transitionInProgress = true
           navigationController.popViewController(animated: true)
        case .changed:
            update(progress)
        case .cancelled, .ended:
            if progress < 0.5 {
                cancel()
            } else {
                finish()
            }
            transitionInProgress = false
        default:
            break
        }
    }

完整的Demo下載地址VCInteractiveNavigationAnimationDemo

最后

未完待續(xù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容