Swift 自訂義非交互轉場動畫(Custom Transition Animation)

iOS 7 之後開放了自定義轉場動畫(custom transition view controllers)的方法,從此之後iOS App就變得更有趣了!

我們在切換ViewController的時候,不再是只有上下或左右的推移,而是有了更豐富的轉場效果。

又比如下面這個Dribble上的效果,Jewelry E-commerce Application

關於轉場(Transition)

在iOS 7 之後官方開放了自定義轉場動畫,並且在iOS 10 引進了全程交互控制。

目前官方官方支持這幾種自定義轉場方式:

  • UIViewController進行presentation和dismissal的過程(需要modalPresentationStyle為.fullScreen或者custom)
  • UINavigationController進行push和pop的過程。
  • UICollectionViewController佈局變化時(需要結合UICollectionViewController和UINavigationController的轉場方式)

上面這張圖來自WWDC2013年的一場關於custom viewController transition的介紹

轉場(Transition)的過程中,作為容器的父ViewController管理者多個子ViewController,但在view的結構上,只會保留一個子ViewController的view。
所以轉場的本質是下一個場景(子ViewController)的View替換掉當前場景(子ViewController以及對應的View)。

這裡指的容器ViewController包括 UINavigationController又或者UITabbarController等等。


轉場代理(Transition Delegate)

需要自定義轉場動畫,第一件事情就是將系統默認的代理改成我們自己的。

  • UIViewControllerTransitioningDelegate(UIViewController的transitioningDelegate屬性)
  • UINavigationControllerDelegate(UINavigationController的delegate屬性)
  • UITabBarControllerDelegate(UITabBarController的delegate屬性)

而我們實現的轉場代理中可以返回動畫控制器(必須)、交互控制器(可選)。

動畫控制器(Animation Controller)

由我們建立一個遵循<UIViewControllerAnimatedTransitioning>協議的類,負責實現轉場動畫的內容。

交互控制器(Interaction Controller)

一個遵循<UIViewControllerInteractiveTransitioning>協議的類,可以讓我們支持使用者通過手勢操作動畫。

轉場上下文(Transition Context)

遵循<UIViewControllerContextTransitioning>,在轉場發生前,系統會給我們所提交的動畫控制器和交互控制器一些信息,比如containerView,是否正在做動畫,動畫是否被取消等。

轉場協調器(Transition Coordinator)

可在執行轉場動畫的同時並行執行其他動畫,它遵循<UIViewControllerTransitionCoordinator>協議,主要用在Modal轉場和交互轉場取消時。

 

其中Transition Delegate和Animation Controller是實現一個轉場動畫最基本的兩個要素,接下來我們從非交互轉場開始。


非交互轉場

首先需要提供轉場代理和動畫控制器,如果沒有提供系統會使用默認的轉場動畫。

動畫控制器協議<UIViewControllerAnimatedTransitioning>

返回轉場動畫的時間(Required)

具體的動畫實現(Required)

轉場動畫完成後可以在這裡做收尾動作(Optional)

我們在實現轉場動畫的方法中會得到一個遵循UIViewControllerContextTransitioning協議的transitionContext,協議中規範了幾個方法:

參與轉場的ViewController,其中的key包括.to和.from

contrainerView,轉場動畫執行的地方。

iOS 8 之後還新增加了viewForKey來直接獲取參與轉場的View,其中的key包括.to和.from

從一個場景轉到另外一個場景的過程中

  • 對於即將消失的場景我們這裡稱為fromView(fromVC),如上圖ViewControllerA。
  • 對於即將出現的場景我們這裡稱為toView(toVC),如上圖ViewControllerB。

通過transitionContext我們可以拿到from (比如上圖的viewControllerA) 或者 to(比如上圖的toViewController) 場景中的內容,來作為轉場動畫的素材。

動畫控制器

我們這裏做了一個HomeVC跳轉到DetailVC的動畫控制器,在轉場的時候會先將fromView的alpha從1過渡到0,再將toView的alpha從0過渡到1。

把fromView和toView放入containerView中,然後在處理漸變的動畫。

在轉場動畫完成的時候執行transitionContext.completeTransition()來通知系統轉場結束了。

轉場代理

  • UINavigationControllerDelegate
  • UITabBarControllerDelegate
  • UIViewControllerTransitioningDelegate

UINavigationControllerDelegate

如果上面的例子,我們在homeVC中,將UINavigationControllerDelegate設定為homeVC本身

我們告訴系統,detailVC的轉場動畫由我們自己來實現。

接著在UINavigationControllerDelegate的方法中提供動畫控制器。

UITabBarControllerDelegate

特殊的Modal轉場

UIViewControllerTransitioningDelegate

對於Presentations 和 Dismissals目前支持兩種形式

  • UIModalPresentationFullScreen
  • UIModalPresentationCustom

使用起來也是非常容易的,設定modalPresentationStyle,給予一個transitioningDelegate。

實現UIViewControllerTransitioningDelegate

需要注意的是:

  • FullScreen模式下,在Presentation結束後,PresentingView會被移出View結構,但因為系統會幫忙處理還原的部分,
    所以操作起來和前面容器類的ViewController轉場操作起來是一樣的。
  • Custom模式下,在Presentation結束後,PresentingView(fromView)未被移出View結構,所以如果在present或者dismiss的
    動畫控制器中將homeViewController的view加入到了container中,在轉場結束後就會跟著container一起被移除而出現黑屏的現象。

即在Custom模式下進行dismiss轉場動畫,如果把toView加入containerView會造成toView消失,而FullScreen模式不會。

presentingView被移除出現黑屏的例子


舉例一個自定義Modal轉場動畫流程的例子

  • 設定轉場代理(setTransitioningDelegate)
  • 執行present動作
  • 提供動畫控制器(animationController)

動畫控制器中

  • 提供一個遵從轉場動畫的執行時間(transitionDuration)
  • 具體的動畫執行過程(animateTransition)
  • 動畫完成時,執行completeTransition()

更多閱讀:

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *