自定義視圖控制器轉場
參考
- GitHub 源碼:shinobicontrols/iOS7-day-by-day
- 天天品嘗iOS7甜點 :: Day 10 :: Custom UIViewController Transitions
轉場效果
默認的 UINavigationController 轉場 push/pop 是這樣的:
現在我們要實現自定義實現視圖控制器轉場效果:
視圖層次結構
視圖層次結構很簡單:一個 UINavigationController 作為窗口的根視圖控制器、而首頁是 UINavigationController 的根視圖控制器、首頁可以 push 到第二頁:
要想實現自定義視圖控制器轉場效果,需要實現 UINavigationControllerDelegate
協議。
在 UINavigationController 實例對象中聲明某個類(HQLNavControllerDelegate
)實現了UINavigationControllerDelegate
協議:
#import "HQLNavigationController.h"
#import "HQLNavControllerDelegate.h"
@interface HQLNavigationController () {
id<UINavigationControllerDelegate> _navDelegate;
}
@end
@implementation HQLNavigationController
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
_navDelegate = [HQLNavControllerDelegate new];
self.delegate = _navDelegate;
}
return self;
}
上面代碼中把實現轉場效果的協議方法封裝成了一個類HQLNavControllerDelegate
:
// ****************************************************
// HQLNavControllerDelegate.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HQLNavControllerDelegate : NSObject <UINavigationControllerDelegate>
@end
// ****************************************************
// HQLNavControllerDelegate.m
#import "HQLNavControllerDelegate.h"
#import "HQLFadeTransition.h"
@implementation HQLNavControllerDelegate
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC{
return [HQLFadeTransition new];
}
@end
而在 HQLNavControllerDelegate
類中又把實現自定義轉場效果的轉場動畫封裝成了一個類 HQLFadeTransition
// ****************************************************
// HQLFadeTransition.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HQLFadeTransition : NSObject <UIViewControllerAnimatedTransitioning>
@end
// ****************************************************
// HQLFadeTransition.m
#import "HQLFadeTransition.h"
@implementation HQLFadeTransition
// @required 方法:返回動畫的時長
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
return 2.0;
}
// @required 方法:實現視圖控制器之間的轉場效果
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
// 1?? viewControllerForKey:獲取與轉場相關的兩個視圖控制器
// UITransitionContextFromViewControllerKey
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// UITransitionContextToViewControllerKey
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 2?? containerView - 動畫發生的容器視圖
UIView *containerView = [transitionContext containerView];
// 3?? 將兩個視圖控制器的子視圖添加到容器視圖
[containerView addSubview:fromVC.view];
[containerView addSubview:toVC.view];
// 4?? 將要轉換到的那個視圖設置為透明
toVC.view.alpha = 0.0;
// 5?? 執行動畫
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
options:0
animations:^{
// 動畫效果
toVC.view.alpha = 1.f;
}
completion:^(BOOL finished) {
// 移除舊視圖控制器視圖
[fromVC.view removeFromSuperview];
// 告訴 transitionContext 上下文,動畫完成啦!
[transitionContext completeTransition:YES];
}];
}
// 轉換完成后調用
- (void)animationEnded:(BOOL) transitionCompleted {
NSLog(@"Transition Completed!");
}
@end
The end.