iOS過場動畫調研筆記

來源:互聯網
上載者:User

iOS過場動畫調研筆記
前言

因項目需要,最近一段時間都在調研iOS的過場動畫。對於我來說這是一個之前沒有太涉及的領域,所以有必要把調研的過程和自己的一些理解紀錄下來

為什麼要自訂過場動畫?

如果大家有關注Material Design和最近一些知名App(如快的、一號專車等)的介面設計和互動的變化,就會發現一種新的趨勢:平滑的頁面過渡。目的旨在於讓使用者盡量少地感覺到頁面之間生硬的切換,從而使App的體驗更加流暢。而iOS原生的兩種常用過場:Push/Pop和Present,和目前流行的趨勢顯然是不太符合的,所以自訂過場動畫的意義就體現出來了。

Transition-iOS的自訂過場簡介

因為之前有部落格對自訂過場做了非常詳細的介紹,我就不贅述了,具體參照這裡 iOS7之定製View Controller轉場效果 (PS:感謝作者)。作者的demo我也有下載看過,他是為每個過場動畫封裝了單獨的類,然後在UIViewController中實現過場切換的代理,在代理中返回相應的動畫效果。對於為過場動畫封裝單獨的類這點我是非常贊同的,但是在UIViewController中實現過場切換的代理這一點我覺得不是特別理想,所以後來我的實現做了修改,最終的效果是在UIViewController中只需要調用一個介面,就可以實現自訂過場的效果。

我的設計分析

首先,我封裝了一個單例模式MBTransition基類,使用單例模式的原因有兩個:

在一個App中,同時存在的過場只會有一個。 實現成單例之後過場對象就不需要依賴於某個UIViewController。

然後.m檔案中為這個類實現過場動畫的幾個代理

#pragma mark UINavigationControllerDelegate methods// Push/Pop時自訂過場的代理// 參數://      navigationController:導航//      operation:導航的操作:Push/Pop/None,可以用來控制在哪種導航的操作下使用自訂過場//      fromVC:執行Push操作的UIViewController//      toVC:被Push的UIViewController- (id)navigationController:(UINavigationController *)navigationController                                  animationControllerForOperation:(UINavigationControllerOperation)operation                                               fromViewController:(UIViewController *)fromVC                                                 toViewController:(UIViewController *)toVC {    return self;}// Present時自訂過場的代理// 參數://      presented:被Present的UIViewController//      presenting:正在執行Present的UIViewController//      source:發起Present的UIViewController(PS:正在執行Present和發起Present的UIViewController是有區別的,如果source是某個UINavigationController下的一個UIViewController,那麼presenting就是這個UINavigationController,如果source不是在類似UINavigationController或者UITabbarController這樣的控制項內,那麼presenting就是source本身)- (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{    return self;}// Dismiss時自訂過場的代理// 參數://      dismissed:被Dismiss掉的UIViewController-(id )animationControllerForDismissedController:(UIViewController *)dismissed{    return self;}#pragma mark - UIViewControllerContextTransitioning// 實現具體自訂過場動畫效果的代理,這個代理也是實現動畫效果的核心// 參數://      transitionContext:過場時的上下文資訊- (void)animateTransition:(id)transitionContext{}// 過場動畫時間的代理// 參數://      transitionContext:過場時的上下文資訊- (NSTimeInterval)transitionDuration:(id)transitionContext{    return self.duration;}

通過上面幾個代理我們可以知道:Push/Pop和Present時過場動畫的代理是不一樣的,所以我建立了一個過場類型的枚舉,用來控制自訂過場在哪種互動下可用:

typedef enum TransitionType{    TransitionTypePush, // Push/Pop過場    TransitionTypePresent // Present過場}TransitionType;

然後在- (NSTimeInterval)transitionDuration:(id)transitionContext代理中我們返回了self.duration,所以我們需要在.h檔案中添加一個變數來儲存過場動畫持續的時間:

@property (nonatomic, assign) NSTimeInterval duration;

接下來我們分析一下 (void)animateTransition:(id)transitionContext 代理中我們做的一些事情:

通過 transitionContext 擷取到過場時切換的兩個UIViewController

// 這裡的 fromVC 和 toVC 代表的是過場是由 fromVC 切換到 toVC 的。// 比如從A介面Push到B介面時,這裡的fromVC是A介面,toVC是B介面,而當B介面被Pop到A介面時,這裡的fromVC就是B介面,toVC就是A介面UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

通過 transitionContext 擷取到執行切換的UIView

// 所有的切換動畫都是基於container來實現的UIView *container = [transitionContext containerView];

通過 transitionContext 擷取到過場的期間

NSTimeInterval duration = [self transitionDuration:transitionContext];

最後通過 transitionContext 擷取到過場時切換的 fromVC 和 toVC 和Push/Present時儲存的 fromVC 和 toVC 進行比較就可以知道目前執行的是Push/Present還是Pop/Dismiss,從而可以為Push/Present和Pop/Dismiss定製不同的動畫效果。

- (BOOL)isReversed:(UIViewController *)fromVC ToVC:(UIViewController *)toVC{    return !([self.fromVC class] == [fromVC class] && [self.toVC class] == [toVC class]);}

所以我們需要在.h檔案中添加兩個成員變數來儲存Push/Present時的 fromVC 和 toVC :

@property (nonatomic, weak) UIViewController *fromVC;@property (nonatomic, weak) UIViewController *toVC;

接下來就是具體的過場動畫部分了,其實就是結合fromVC的view、toVC的view和container做一些動畫效果,因為跟做普通的動畫沒有什麼區別,所以這個部分我就不具體描述了。

最後是提供給外部調用的介面,內容如下:

- (void)setTransitionWithFromViewController:(UIViewController *)fromVC ToViewController:(UIViewController *)toVC TransitionType:(TransitionType)type Duration:(NSTimeInterval)duration{    self.fromVC = fromVC;    self.toVC = toVC;    self.duration = duration;    if (type == TransitionTypePush) {        self.fromVC.navigationController.delegate = self;    }else if (type == TransitionTypePresent){        self.fromVC.transitioningDelegate = self;        self.toVC.transitioningDelegate = self;    }}

上面程式碼片段所做的事情就是對一些參數進行儲存,然後根據 TransitionType 來設定相應的代理。

特點如果要實現其他自訂過場,只需要繼承MBTransition,然後重寫 (void)animateTransition:(id)transitionContext 代理即可。 使用者只需調用一個介面即可實現自訂過場,降低了代碼耦合。互動切換動畫

互動式動畫主要是指使用者可以通過手勢控制整個動畫的過程,這個部分我目前還沒有研究…

碰到的一些坑當UIViewController是UITabbarController或者UINavigationController的一個childViewController時,通過 [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey][transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] 拿到的UIViewController其實是UITabbarController或者UINavigationController,所以在調用介面時,要注意傳入的 fromVC 和 toVC 其實是這個UIViewController的UITabbarController或者UINavigationController。

如果採用Push/Pop的方式,當fromVC屬於UITabbarController的一個childViewController,且在 toVC 上不能顯示UITabbarController的UITabBar時,UITabbarController的UITabBar會造成很大的麻煩:

如果使用設定hidesBottomBarWhenPushed為true的方式,那麼UITabBar的動畫不能定製,只能是預設的從右至左和從左至右。 如果使用自訂的方式顯示和隱藏UITabBar,因為AutoLayout的原因,後期問題會更多…

所以在這種情況下建議使用Present的方式切換到新的介面,當然如果大家有好的解決方案也希望能分享給我,謝謝!

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.