iOS自定義轉場動畫例程與需要注意的問題
OS提供了一些內置的轉場類型。Navigation controllers用push和pop來有層次地導航信息,tab bar controllers用切換tabs來在各部分之間跳轉,所有的視圖控制器可以根據特定任務模態化地present和dismiss另一個視圖控制器。
API介紹
每一個自定義轉場涉及三個主要對象:
from view controller (消失的那個)
to view controller (出現的那個)
一個動畫控制器
自定義轉場和在自定義之前一樣。對于push和pop,意味著調用UINavigationController的push-、pop-、或者set-方法來修改視圖控制器的堆棧。對于切換tabs,意味著修改UITabBarController的selectedIndex或selectedViewController屬性。對于modal,則意味著調用?[UIViewController presentViewController: animated: completion: ]或?[UIViewController dismissViewControllerAnimated: completion: ]。無論哪種情況,這個步驟都確定了“from view controller”和“to view controller”。
使用一個自定義轉場,你需要一個動畫控制器。對我來說這是自定義動畫轉場中最令人困惑的部分,因為每種轉場需要的動畫控制器不同。下表展示了如何為每種轉場提供動畫控制器。記著,委托方法總是返回動畫控制器。
動畫控制器可以是任何遵守UIViewControllerAnimatedTransitioning協議的對象。該協議聲明了兩個必須要實現的方法。一個提供了動畫的時間,另一個執行了動畫。這些方法調用時都傳遞一個上下文。上下文提供了入口來訪問信息和你創建自定義轉場需要的對象。以下是一些重點:
from view controller
to view controller
兩個視圖控制器view的第一幀和最后一幀
container view,根據這篇文檔,“作為的轉場中視圖的父視圖”
重要:上下文還實現了-completeTransition:,你必須在你自定義轉場結束時調用一次。
這是關于自定義轉場所有你需要知道的。讓我們來看一些例子!
例子
所有這些例子都可以在GitHub找到,你可以克隆這些倉庫,然后邊往下看邊試試這些例子。
這三個例子都直接或子類化地使用了TWTExampleViewController。它只是設置了視圖的背景顏色,同時使你能夠通過點擊任何地方來結束例子回到主菜單。
輕彈push和pop
在這個例子中,目標是讓push和pop使用flip動畫而不是標準的slide動畫。一開始我建立一個navigation controller并把TWTPushExampleViewController的實例當作root。TWTPushExampleViewController添加了一個叫“Push”的右按鈕到導航欄。點擊它時,一個新的TWTPushExampleViewController的實例被壓入navigation的堆棧:
- (void)pushButtonTapped
{
TWTPushExampleViewController *viewController = [[TWTPushExampleViewController alloc] init];
viewController.delegate = self.delegate;
[self.navigationController pushViewController:viewController animated:YES];
}
navigation controller的設置發生在TWTExamplesListViewController(運行demo主菜單的視圖控制器)。注意,它把自己置為navigation controller的委托:
- (void)presentPushExample
{
TWTPushExampleViewController *viewController = [[TWTPushExampleViewController alloc] init];
viewController.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
navigationController.delegate = self;
[self presentViewController:navigationController animated:YES completion:nil];
}
這意味著當navigation controller的轉場即將開始時,TWTExamplesListViewController將收到委托信息,并有機會返回一個動畫控制器。對于這種轉場,我使用一個TWTSimpleAnimationController的實例,它是一個+[UIView transitionFromView: toView: duration: options: completion:]的封裝:
- (id)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
TWTSimpleAnimationController *animationController = [[TWTSimpleAnimationController alloc] init];
animationController.duration = 0.5;
animationController.options = ( operation == UINavigationControllerOperationPush
? UIViewAnimationOptionTransitionFlipFromRight
: UIViewAnimationOptionTransitionFlipFromLeft);
returnanimationController;
}
如果轉場是一個push,我使用一個從右側的flip,否則,我使用一個從左側的flip。
以下是TWTSimpleAnimationController的實現:
- (NSTimeInterval)transitionDuration:(id)transitionContext
{
returnself.duration;
}
- (void)animateTransition:(id)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];
[toViewController.view layoutIfNeeded];
[UIView transitionFromView:fromViewController.view
toView:toViewController.view
duration:self.duration
options:self.options
completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
記著,這兩個方法是UIViewControllerAnimatedTransitioning協議的一部分。在動畫控制器運行自定義轉場的時候,它們被UIKit調用。
這里有一些關于animateTransition:需要注意的事情:
from view controller,to view controller,以及to view controller的最后一幀都從轉場的上下文中提取。其中還有一些其他可提取的信息,但在當前情況下,并不需要所有信息。
+[UIView transitionFromView: toView: duration: options: completion:]負責有層次地添加和刪除視圖。在后面的例子中,我將展示一種手動完成的情況。
在轉場的completion代碼塊中,我調用[transitionContext completeTransition: YES]來告訴系統轉場結束了。如果你忘了這樣做,你將無法與app交互。如果出現這種情況,先檢查這個原因。
以上就是全部!現在有一些值得嘗試的東西:
改變動畫的持續時間來看看它如何影響navigation bar的動畫。
把動畫選項由flip改為page curls。
找一個方法讓navigation的堆棧中的每個視圖控制器能指定自己的動畫控制器。看看在本文最后的推薦模式中提出的方法。
非常好我支持^.^
(0) 0%
不好我反對
(0) 0%