1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        iOS 自定義轉(zhuǎn)場(chǎng)動(dòng)畫

        共 10032字,需瀏覽 21分鐘

         ·

        2023-02-25 11:41

        ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????


        簡(jiǎn)介

        在日常開發(fā)中動(dòng)畫是必不可少的,蘋果也為iOS開發(fā)提供了很多好的動(dòng)畫效果,作為iOS開發(fā)者自然需要對(duì)動(dòng)畫有所了解。在這些動(dòng)畫中,有一種動(dòng)畫是用于一個(gè)場(chǎng)景轉(zhuǎn)換到另一個(gè)場(chǎng)景的過渡動(dòng)畫,我們稱之為轉(zhuǎn)場(chǎng)動(dòng)畫,本文主要內(nèi)容是關(guān)于轉(zhuǎn)場(chǎng)動(dòng)畫的。

        轉(zhuǎn)場(chǎng),顧名思義是場(chǎng)景的轉(zhuǎn)換,即界面由一個(gè)場(chǎng)景轉(zhuǎn)換到另一個(gè)場(chǎng)景。在iOS中可以分為視圖控制器轉(zhuǎn)換視圖的轉(zhuǎn)換兩個(gè)層次,本文的主要結(jié)構(gòu)如下:

        • 轉(zhuǎn)場(chǎng)動(dòng)畫簡(jiǎn)介
        • 視圖控制器轉(zhuǎn)場(chǎng)的實(shí)現(xiàn)機(jī)制 -- 五大協(xié)議
        • 視圖轉(zhuǎn)場(chǎng)的實(shí)現(xiàn) -- CATransition

        視圖控制器轉(zhuǎn)場(chǎng) -- View Controller Transition

        在iOS 7之前,系統(tǒng)已經(jīng)提供了一些默認(rèn)的視圖控制器轉(zhuǎn)場(chǎng)動(dòng)畫,但是這些動(dòng)畫是完全由系統(tǒng)實(shí)現(xiàn)的,不能進(jìn)行自定義。在iOS 7的時(shí)候,系統(tǒng)開放了部分API,使得自定義轉(zhuǎn)場(chǎng)動(dòng)畫成為現(xiàn)實(shí)。

        自定義轉(zhuǎn)場(chǎng)動(dòng)畫相關(guān)的API主要包括五個(gè)協(xié)議,下面分別介紹下:

        • 轉(zhuǎn)場(chǎng)代理
        • 轉(zhuǎn)場(chǎng)上下文環(huán)境協(xié)議
        • 動(dòng)畫控制器協(xié)議
        • 交互控制器協(xié)議
        • 轉(zhuǎn)場(chǎng)協(xié)調(diào)器協(xié)議

        1、轉(zhuǎn)場(chǎng)代理

        視圖控制器中的視圖顯示在屏幕上有兩種方式:1、內(nèi)嵌在容器中,例如UINavigationController、UITabBarController、 2、模態(tài)彈出,即Present/dismiss

        對(duì)于這些方式,系統(tǒng)在對(duì)應(yīng)的代理協(xié)議中都提供了關(guān)于轉(zhuǎn)場(chǎng)動(dòng)畫的相關(guān)方法,下面逐個(gè)分析下:

        1.1 導(dǎo)航欄代理 - UINavigationControllerDelegate

        optional func navigationController(_ navigationController: UINavigationController, 
                    animationControllerFor operation: UINavigationController.Operation, 
                                      from fromVC: UIViewController, 
                                        to toVC: UIViewController)
         -> UIViewControllerAnimatedTransitioning?

        該方法返回一個(gè)遵守UIViewControllerAnimatedTransitioning協(xié)議的可選對(duì)象,該協(xié)議即為動(dòng)畫控制器協(xié)議,在后文會(huì)專門介紹,這里先做個(gè)簡(jiǎn)介。我們可以在遵守該協(xié)議的類中進(jìn)行轉(zhuǎn)場(chǎng)動(dòng)畫的設(shè)計(jì),如果返回的對(duì)象為nil,則保持系統(tǒng)動(dòng)畫,不會(huì)使用自定義動(dòng)畫。

        參數(shù)中,operation是一個(gè)枚舉類型,其case為 .none、.push、.pop;fromVC表示push/pop動(dòng)作發(fā)生時(shí)顯示的ViewController,即動(dòng)畫之前的ViewController,toVC表示動(dòng)畫結(jié)束后的ViewController,例如push動(dòng)作由 A -> B,則fromVC為A,toVC為B,當(dāng)發(fā)生pop動(dòng)作 B -> A時(shí),fromVC為B,toVC為A。

        optional func navigationController(_ navigationController: UINavigationController, 
                  interactionControllerFor animationController: UIViewControllerAnimatedTransitioning)
         -> UIViewControllerInteractiveTransitioning?

        該方法返回一個(gè)遵守UIViewControllerInteractiveTransitioning協(xié)議的可選對(duì)象,該協(xié)議對(duì)象為一個(gè)可交互的轉(zhuǎn)場(chǎng)對(duì)象,即交互控制協(xié)議對(duì)象,該對(duì)象定義了轉(zhuǎn)場(chǎng)動(dòng)畫的交互行為。

        1.2 模態(tài)的代理 - UIViewControllerTransitioningDelegate

        optional func animationController(forPresented presented: UIViewController, 
                               presenting: UIViewController, 
                                   source: UIViewController)
         -> UIViewControllerAnimatedTransitioning?

        optional func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?

        這兩個(gè)方法均返回一個(gè)遵守UIViewControllerAnimatedTransitioning協(xié)議的可選對(duì)象,用于在模態(tài)彈出時(shí),返回自定義轉(zhuǎn)場(chǎng)動(dòng)畫的對(duì)象。與導(dǎo)航欄有所不同的是,模態(tài)彈出分為了 present 和 dismiss 兩個(gè)方法。

        在present方法中,presented表示被present的ViewController,source表示調(diào)用方法的ViewController,presenting可以與source相同,也可以不相同,當(dāng)source作為一個(gè)childViewController時(shí),presenting為source的父控制器,否則presenting與source相同。

        optional func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?

        optional func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?

        與設(shè)置動(dòng)畫控制器的方法一樣,在設(shè)置交互控制器時(shí),模態(tài)方式也分為了 present 和 dismiss 兩個(gè)方法,分別用來設(shè)置present 和 dismiss時(shí)的交互行為。

        1.3 tabbar的轉(zhuǎn)場(chǎng)代理

        optional func tabBarController(_ tabBarController: UITabBarController, 
        animationControllerForTransitionFrom fromVC: UIViewController, 
                                    to toVC: UIViewController)
         -> UIViewControllerAnimatedTransitioning?

        optional func tabBarController(_ tabBarController: UITabBarController, 
              interactionControllerFor animationController: UIViewControllerAnimatedTransitioning)
         -> UIViewControllerInteractiveTransitioning?

        與上文所述一致,這兩個(gè)方法分別返回動(dòng)畫控制器和交互控制器。

        2、轉(zhuǎn)場(chǎng)上下文

        轉(zhuǎn)場(chǎng)上下文是一個(gè)遵守UIViewControllerContextTransitioning協(xié)議的對(duì)象,該對(duì)象由系統(tǒng)自動(dòng)創(chuàng)建,無需我們進(jìn)行管理。UIViewControllerContextTransitioning協(xié)議包含如下API:

        @available(iOS 2.0, *) var containerView: UIView { get }

        containerView是一個(gè)容器,轉(zhuǎn)場(chǎng)動(dòng)畫前后的View以及要添加的動(dòng)畫視圖都是添加在這個(gè)容器中的。事實(shí)上,該容器的類型是UIViewControllerWrapperView,無論是自定義轉(zhuǎn)場(chǎng),還是系統(tǒng)定義的轉(zhuǎn)場(chǎng),最終都是添加在該view上,并且作為一個(gè)全局的上下文,該view只存在一份,因此需要合理管理其子視圖。

        @available(iOS 2.0, *) func viewController(forKey key: UITransitionContextViewControllerKey) -> UIViewController?

        根據(jù)UITransitionContextViewControllerKeyfromto獲取轉(zhuǎn)場(chǎng)前后的ViewController,并且與上文所述fromVC和toVC一致,轉(zhuǎn)場(chǎng)前后的ViewController是可逆的。例如push時(shí) A -> B,則A是 fromVC, B是 toVC;在pop回去是二者的位置則發(fā)生了對(duì)調(diào)。

        @available(iOS 8.0, *) func view(forKey key: UITransitionContextViewKey) -> UIView?

        在iOS 7及之前,我們只能通過獲取到轉(zhuǎn)場(chǎng)前后的ViewController,進(jìn)而獲取其view來獲取轉(zhuǎn)場(chǎng)前后的視圖,但是在iOS 8及以后,我們可以直接獲取轉(zhuǎn)場(chǎng)前后的View。

        var transitionWasCancelled: Bool { get }

        該屬性為一個(gè)只讀的計(jì)算屬性,表示轉(zhuǎn)場(chǎng)是否被取消。當(dāng)轉(zhuǎn)場(chǎng)動(dòng)畫為一個(gè)可交互式動(dòng)畫時(shí),動(dòng)畫進(jìn)行過程中可以手動(dòng)觸發(fā)取消,如果取消了則該屬性為true,而如果沒有取消,則為false,對(duì)于一個(gè)非交互式動(dòng)畫,則該值一直為false。

        func completeTransition(_ didComplete: Bool)

        當(dāng)轉(zhuǎn)場(chǎng)動(dòng)畫完成或者被取消時(shí),調(diào)用該方法。

        3、動(dòng)畫控制器

        動(dòng)畫控制器協(xié)議定義了一系列API,用以配置實(shí)現(xiàn)轉(zhuǎn)場(chǎng)動(dòng)畫。我們創(chuàng)建一個(gè)自己的類,并遵守該協(xié)議,然后通過轉(zhuǎn)場(chǎng)代理將自定義動(dòng)畫的Trasnsition返回給系統(tǒng)。

        動(dòng)畫控制器中有兩個(gè)主要的API,分別為:

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

        該方法返回一個(gè)時(shí)長(zhǎng),在該方法中定義轉(zhuǎn)場(chǎng)動(dòng)畫持續(xù)的時(shí)間

        func animateTransition(using transitionContext: UIViewControllerContextTransitioning)

        在該方法中,定義轉(zhuǎn)場(chǎng)要做的動(dòng)畫。

        4、交互控制器

        交互控制器協(xié)議是用來配置轉(zhuǎn)場(chǎng)動(dòng)畫的交互事件的,實(shí)際的動(dòng)畫依然由動(dòng)畫控制器來完成。系統(tǒng)定義了UIViewControllerInteractiveTransitioning協(xié)議,但是在實(shí)際使用時(shí),我們不會(huì)直接遵守該協(xié)議,而是繼承UIPercentDrivenInteractiveTransition類。

        UIPercentDrivenInteractiveTransition是系統(tǒng)提供的類,根據(jù)蘋果官方文檔的解釋,創(chuàng)建一個(gè)交互式動(dòng)畫對(duì)象最簡(jiǎn)單的方式就是繼承該類,如下圖所示。

        該類的API主要有如下幾個(gè):

        open var duration: CGFloat { get } // 動(dòng)畫時(shí)長(zhǎng),根據(jù)transitionDuration:的返回值確定

        open var percentComplete: CGFloat { get }  // 完成百分比

        open func update(_ percentComplete: CGFloat)  // 更新動(dòng)畫完成百分比

        open func cancel()  // 取消動(dòng)畫

        open func finish()  // 完成動(dòng)畫

        // 上訴三個(gè)方法對(duì)應(yīng)UIViewControllerContextTransitioning協(xié)議中的 updateInteractiveTransition、cancelInteractiveTransition()、finishInteractiveTransition()方法

        5、轉(zhuǎn)場(chǎng)協(xié)調(diào)器

        轉(zhuǎn)場(chǎng)協(xié)調(diào)器用于幫助做一些輔助動(dòng)畫,由系統(tǒng)進(jìn)行創(chuàng)建,我們通過UIViewController的分類中的屬性即可獲取,代碼如圖:

        在UIViewControllerTransitionCoordinator中定義了如下API

        func animate(alongsideTransition animation: ((UIViewControllerTransitionCoordinatorContext) -> Void)?, completion: ((UIViewControllerTransitionCoordinatorContext) -> Void)? = nil) -> Bool

        在該方法中添加動(dòng)畫,當(dāng)轉(zhuǎn)場(chǎng)動(dòng)畫執(zhí)行完畢后,會(huì)繼續(xù)執(zhí)行animation閉包中的動(dòng)畫,而如果使用UIView.animate(withDuration的方式添加動(dòng)畫,則會(huì)在轉(zhuǎn)場(chǎng)動(dòng)畫執(zhí)行時(shí),動(dòng)畫就已經(jīng)執(zhí)行完畢。

        CATransition

        上文介紹了ViewController間的轉(zhuǎn)場(chǎng)實(shí)現(xiàn)機(jī)制,在CoreAnimation框架中,還有一個(gè)動(dòng)畫類用來做layer級(jí)的轉(zhuǎn)場(chǎng),即CATransition。CATransition是作用于CALayer上的,因此需要將CATransition添加到view的layer屬性上。

        CATransition是繼承自CAAnimation的類,其自己所包含的屬性由:

        open var type: CATransitionType

        該屬性表示轉(zhuǎn)場(chǎng)的類型,例如 fade、push、moveIn等,具體效果可參考CATransitionDemo[1]

        open var subtype: CATransitionSubtype?復(fù)制代碼

        該屬性表示轉(zhuǎn)場(chǎng)的方向,但是對(duì)于fade這種與方向無關(guān)的轉(zhuǎn)場(chǎng),該屬性是沒有效果的。

        /* The amount of progress through to the transition at which to begin
             * and end execution. Legal values are numbers in the range [0,1].
             * `endProgress' must be greater than or equal to `startProgress'.
             * Default values are 0 and 1 respectively. */

            
        open var startProgress: Float

        open var endProgress: Float

        這兩個(gè)屬性分別表示開始時(shí)的進(jìn)度和結(jié)束時(shí)的進(jìn)度,結(jié)合父類的duration屬性,可以控制動(dòng)畫的開始和結(jié)束為止。需要注意的是,這兩個(gè)屬性的值為[0, 1],并且 startProgress要小于 endProgress。

        總結(jié)

        本文主要介紹了轉(zhuǎn)場(chǎng)動(dòng)畫的實(shí)現(xiàn)流程,主要有如下兩部分內(nèi)容:

        • 1、ViewController的轉(zhuǎn)場(chǎng)

        • 2、View的轉(zhuǎn)場(chǎng)

        分別對(duì)應(yīng)轉(zhuǎn)場(chǎng)的五大協(xié)議CATransition。本文只是介紹了相關(guān)的API使用,具體Demo可參照網(wǎng)上的CATransitionDemo[2]VCTransitionsLibrary[3]。

        本文參考文檔:

        • iOS 視圖控制器轉(zhuǎn)場(chǎng)詳解[4]
        • 使用 UIPercentDrivenInteractiveTransition[5]

        感謝兩位博主的知識(shí)分享,對(duì)本文的不足之處也歡迎大家指正。

        參考資料

        [1]

        CATransitionDemo: https://github.com/GuoYongming/CAtransitionDemo

        [2]

        CATransitionDemo: https://github.com/GuoYongming/CAtransitionDemo

        [3]

        VCTransitionsLibrary: https://github.com/ColinEberhardt/VCTransitionsLibrary#using-an-interaction-controller

        [4]

        iOS 視圖控制器轉(zhuǎn)場(chǎng)詳解: https://blog.devtang.com/2016/03/13/iOS-transition-guide/#Chapter1

        [5]

        使用 UIPercentDrivenInteractiveTransition: https://zhangbuhuai.com/post/uipercentdriveninteractivetransition.html


        來源:奔跑的不將就

        https://juejin.cn/post/7072598244727095304


        -End-

        最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

        點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

        在看點(diǎn)這里好文分享給更多人↓↓

        瀏覽 54
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产精品一色哟哟哟 | 无码人妻激情 | 女人18毛片一区二区三区 | 亚洲人人爱 | 女生脱了裤子让男生捅 | 做爱免费网站 | 五月天色婷婷丁香 | 《高潮3》hd未删减在线 周妍希裸体 | 成人视频在线观看中文字幕高清无码 | 自拍偷拍精品网 |