iOS自定義 Transitions 動畫總結

hejunm發表於2017-12-21

在iOS中,當導航控制器呼叫 [navigationController pushViewController:secondViewController animated:YES]時,系統會提供一個過渡的動畫來提高使用者體驗。另外,一個控制器present(或者dismiss)另一個控制器時([self presentViewController:secondViewController animated:YES completion:NULL])系統也會提供相應的過渡動畫。為了使app互動效果更加精彩,iOS為我們提供了在不同場景下自定義過渡動畫以及通過手勢控制過渡進度的實現方案。效果先看這個demo效果

自定義 Transitions 動畫的效果由實現了UIViewControllerAnimatedTransitioning協議的例項定製; 手勢控制過渡進度由實現了UIViewControllerInteractiveTransitioning協議的例項定製。在不同的Transition場景下, 我們通過不同的代理方法向系統提供自定義的遵守UIViewControllerAnimatedTransitioning協議的物件和遵守UIViewControllerInteractiveTransitioning協議的物件。 知道如何將自己定義的UIViewControllerAnimatedTransitioning物件以及UIViewControllerInteractiveTransitioning物件提供會給系統;並且知道如何實現UIViewControllerInteractiveTransitioning協議以及實現UIViewControllerInteractiveTransitioning協議, 你就可以自如的實現自己的Transition動畫了。


一,自定義Transitions動畫使用場景

1, 一個控制器present另一個控制器的自定義轉換動畫

這種場景在呼叫[self presentViewController:secondViewController animated:YES completion:NULL][self dismissViewControllerAnimated:YES completion:NULL];
時產生。實現步驟如下:

(1) 對被present的控制器設定transitioning代理物件 secondViewController.transitioningDelegate = presentationController;
presentationController是實現協議UIViewControllerTransitioningDelegate 的例項。 同時設定secondViewController . modalPresentationStyle = UIModalPresentationCustom;

(2) 代理物件要實現UIViewControllerTransitioningDelegate 協議的方法,在代理方法中返回遵守UIViewControllerAnimatedTransitioning協議和UIViewControllerInteractiveTransitioning協議的物件。

@protocol UIViewControllerTransitioningDelegate <
NSObject>
@optional//返回用於present的自定義transition動畫。- (nullable id <
UIViewControllerAnimatedTransitioning>
)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
//返回用於dismiss時的自定義transition動畫。- (nullable id <
UIViewControllerAnimatedTransitioning>
)animationControllerForDismissedController:(UIViewController *)dismissed;
//返回用於present時的可進行手勢互動的transition動畫。- (nullable id <
UIViewControllerInteractiveTransitioning>
)interactionControllerForPresentation:(id <
UIViewControllerAnimatedTransitioning>
)animator;
//返回用於dismiss時的可進行手勢互動的transition動畫。 - (nullable id <
UIViewControllerInteractiveTransitioning>
)interactionControllerForDismissal:(id <
UIViewControllerAnimatedTransitioning>
)animator;
//這個在自定義PresentationController時使用。下面的sample code有相應demo.- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0);
@end複製程式碼

2, UINavigationController 中控制器的transition

這種場景在[navigationController pushViewController:secondViewController animated:YES][self.navigationController popViewControllerAnimated:YES];
下產生。實現步驟如下:

(1) 設定 導航控制器的delegate : self.navigationController.delegate = self;

(2) 實現代理方法, 在代理方法中返回實現UIViewControllerAnimatedTransitioning,和UIViewControllerInteractiveTransitioning(手勢控制切換過程)協議的物件。

//返回可用於進行手勢互動的transition動畫。 - (nullable id <
UIViewControllerInteractiveTransitioning>
)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id <
UIViewControllerAnimatedTransitioning>
) animationController NS_AVAILABLE_IOS(7_0);
//返回自定義過渡動畫- (nullable id <
UIViewControllerAnimatedTransitioning>
)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
複製程式碼

3, UITabBarController中切換控制器的transition

在預設情況下,UITabBarController切換控制器是沒有過渡動畫效果的。通過自定義Transitiond動畫為切換控制器加上過渡效果。其實現步驟如下:

(1) 設定 UITabBarController例項的代理物件: self.tabBarController.delegate = self;
代理物件必須遵守UITabBarControllerDelegate協議。

(2) 實現代理方法如下代理方法, 在代理方法中返回遵守相應協議的物件。

- (nullable id <
UIViewControllerInteractiveTransitioning>
)tabBarController:(UITabBarController *)tabBarController interactionControllerForAnimationController: (id <
UIViewControllerAnimatedTransitioning>
)animationController NS_AVAILABLE_IOS(7_0);
- (nullable id <
UIViewControllerAnimatedTransitioning>
)tabBarController:(UITabBarController *)tabBarController animationControllerForTransitionFromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
複製程式碼

二,實現協議UIViewControllerAnimatedTransitioning

- (NSTimeInterval)transitionDuration:(nullable id <
UIViewControllerContextTransitioning>
)transitionContext{
//返回執行轉換控制器的時長
}- (void)animateTransition:(id <
UIViewControllerContextTransitioning>
)transitionContext{
/** (1), 從transitionContext 獲取執行動畫需要的資訊例如 UIView *containerView = transitionContext.containerView;
UIView *fromView;
UIView *toView;
(2),將toView 新增到containerView 中(所有的要執行的動畫都需要在這裡面完成) (3),執行動畫 [UIView animateWithDuration:transitionDuration animations:^{
//在這裡執行一些動畫
} completion:^(BOOL finished) {
//動畫結束後,一定要呼叫 BOOL wasCancelled = [transitionContext transitionWasCancelled];
[transitionContext completeTransition:!wasCancelled];

} */
}
}複製程式碼

三,實現協議 UIViewControllerInteractiveTransitioning

- (void)startInteractiveTransition:(id<
UIViewControllerContextTransitioning>
)transitionContext{
//在這裡做些初始化的操作 [super startInteractiveTransition:transitionContext];

}複製程式碼

注意:(1) 在獲取UIViewControllerAnimatedTransitioning的代理方法中,如果有返回實現UIViewControllerAnimatedTransitioning協議 的物件, 那麼就使用customer transition; 如果返回nil, 就使用系統預設的效果。(2) 在獲取 UIViewControllerInteractiveTransitioning的代理方法中, 如果返回實現UIViewControllerInteractiveTransitioning協議的物件, 那麼transition過程就是通過手勢控制的; 如過返回nil,就直接轉換。


四, 使用手勢控制Transition 的大致流程

將手勢識別器新增到合適的view上, 根據監聽到的手勢的狀態做出相應操作

switch (gestureRecognizer.state)    { 
case UIGestureRecognizerStateBegan: /** 監聽到手勢開始,觸發transition。 也就是呼叫下面的某個方法 [self.navigationController pushViewController:secondViewController animated:YES];
(導航控制器中, 或者pop) 或者[self presentViewController:secondViewController animated:YES completion:NULL];
(presentViewController, 或者dismiss) 或者[tabBarController setSelectedIndex:2];
(tabBarController ) */ break;
case UIGestureRecognizerStateChanged: /** 更新進度 */ [self updateInteractiveTransition:[self percentForGesture:gestureRecognizer]];
break;
case UIGestureRecognizerStateEnded: // Dragging has finished. // Complete or cancel, depending on how far we've dragged. //根據進度決定是finishInteractiveTransition 還是 cancelInteractiveTransition 。 if ([self percentForGesture:gestureRecognizer] >
= 0.5f) [self finishInteractiveTransition];
else [self cancelInteractiveTransition];
break;
default: // Something happened. cancel the transition. [self cancelInteractiveTransition];
break;

}
複製程式碼

五,Sample Code

具體程式碼與理論相結合往往事半功倍。推薦給大家一些比較好的Sample Code.

來源:https://juejin.im/post/5a30ca216fb9a045204c3571

相關文章