在iOS7之前,View Controller的切換主要有4種:
- Push/Pop,NavigationViewController
- Present and dismis Modal
- UITabBarController
- addChildViewController(一般用于自定義的繼承于 UIViewController 的容器子類)
iOS5,調用- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(5_0);
(1)前面3種方法這里就不多說了,很常見的系統方法.至于第四種,我在前面文章-剖析網易標簽欄的效果中已經做了闡述,但是它提供的容器轉場動畫只可以實現一些簡單的UIView動畫,但是難以重用,耦合高.
(2)關鍵的API:
A.動畫控制器 (Animation Controllers) 遵從 UIViewControllerAnimatedTransitioning 協議,并且負責實際執行動畫。
B.交互控制器 (Interaction Controllers) 通過遵從 UIViewControllerInteractiveTransitioning 協議來控制可交互式的轉場。
C.轉場代理 (Transitioning Delegates) 根據不同的轉場類型方便的提供需要的動畫控制器和交互控制器。
其中UINavigationControllerDelegate delegate 中新增了2個方法給NavigationController
UIViewControllerTransitioningDelegate 新增transitioningDelegate 給Modal的Present和Dismis
復制代碼 代碼如下:
UITabBarControllerDelegate delegate
- (id <UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController
interactionControllerForAnimationController: (id <UIViewControllerAnimatedTransitioning>)animationController NS_AVAILABLE_IOS(7_0);
- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
D.轉場上下文 (Transitioning Contexts) 定義了轉場時需要的元數據,比如在轉場過程中所參與的視圖控制器和視圖的相關屬性。 轉場上下文對象遵從 UIViewControllerContextTransitioning 協議,并且這是由系統負責生成和提供的。
E.轉場協調器(Transition Coordinators) 可以在運行轉場動畫時,并行的運行其他動畫。 轉場協調器遵從 UIViewControllerTransitionCoordinator 協議。
(3)新的API主要提供了2種VC切換的方式:
A.非交互式切換,即定義一種從一個VC到另一個VC的動畫效果,切換的時候自動播放,
B.交互式切換,這種方式同樣需要定義動畫效果,只是這個動畫效果會根據跟隨交互式手勢來切換VC并同時播放動畫效果。iOS7提供了一個默認的基于百分比的動畫實現 UIPercentDrivenInteractiveTransition,而且根據WWDC的說明,最簡單的實現交互式動畫的方法就是通過繼承 UIPercentDrivenInteractiveTransition。蘋果給我們開發者提供的是都是協議接口,所以我們能夠很好的單獨提出來寫成一個個類,在里面實現我們各種自定義效果.
(4)來看看實現UIViewControllerAnimatedTransitioning的自定義動畫類
復制代碼 代碼如下:
/**
* 自定義的動畫類
* 實現協議------>@protocol UIViewControllerAnimatedTransitioning
* 這個接口負責切換的具體內容,也即“切換中應該發生什么”
*/
@interface MTHCustomAnimator : NSObject <UIViewControllerAnimatedTransitioning>
@end
@implementation MTHCustomAnimator
// 系統給出一個切換上下文,我們根據上下文環境返回這個切換所需要的花費時間
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 1.0;
}
// 完成容器轉場動畫的主要方法,我們對于切換時的UIView的設置和動畫都在這個方法中完成
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
// 可以看做為destination ViewController
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 可以看做為source ViewController
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// 添加toView到容器上
// 如果是XCode6 就可以用這段
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
// iOS8 SDK 新API
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
//UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
[[transitionContext containerView] addSubview:toView];
}else{
// 添加toView到容器上
[[transitionContext containerView] addSubview:toViewController.view];
}
// 如果是XCode5 就是用這段
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0.0;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
// 動畫效果有很多,這里就展示個左偏移
fromViewController.view.transform = CGAffineTransformMakeTranslation(-320, 0);
toViewController.view.alpha = 1.0;
} completion:^(BOOL finished) {
fromViewController.view.transform = CGAffineTransformIdentity;
// 聲明過渡結束-->記住,一定別忘了在過渡結束時調用 completeTransition: 這個方法
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
PS:從協議中兩個方法可以看出,上面兩個必須實現的方法需要一個轉場上下文參數,這是一個遵從UIViewControllerContextTransitioning 協議的對象。通常情況下,當我們使用系統的類時,系統框架為我們提供的轉場代理(Transitioning Delegates),為我們創建了轉場上下文對象,并把它傳遞給動畫控制器。
復制代碼 代碼如下:
// MainViewController
@interface MTHMainViewController () <UINavigationControllerDelegate,UIViewControllerTransitioningDelegate>
@property (nonatomic,strong) MTHCustomAnimator *customAnimator;
@property (nonatomic,strong) PDTransitionAnimator *minToMaxAnimator;
@property (nonatomic,strong) MTHNextViewController *nextVC;
// 交互控制器 (Interaction Controllers) 通過遵從 UIViewControllerInteractiveTransitioning 協議來控制可交互式的轉場。
@property (strong, nonatomic) UIPercentDrivenInteractiveTransition* interactionController;
@end
@implementation MTHMainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = @"Demo";
self.view.backgroundColor = [UIColor yellowColor];
// 設置代理
self.navigationController.delegate = self;
// 設置轉場動畫
self.customAnimator = [[MTHCustomAnimator alloc] init];
self.minToMaxAnimator = [PDTransitionAnimator new];
self.nextVC = [[MTHNextViewController alloc] init];
// Present的代理和自定義設置
_nextVC.transitioningDelegate = self;
_nextVC.modalPresentationStyle = UIModalPresentationCustom; (貌似有BUG)換成modalTransitionStyle = UIModalPresentationCustom
// Push
UIButton *pushButton = [UIButton buttonWithType:UIButtonTypeSystem];
pushButton.frame = CGRectMake(140, 200, 40, 40);
[pushButton setTitle:@"Push" forState:UIControlStateNormal];
[pushButton addTarget:self action:@selector(push) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:pushButton];
// Present
UIButton *modalButton = [UIButton buttonWithType:UIButtonTypeSystem];
modalButton.frame = CGRectMake(265, 500, 50, 50);
[modalButton setTitle:@"Modal" forState:UIControlStateNormal];
[modalButton addTarget:self action:@selector(modal) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:modalButton];
// 實現交互操作的手勢
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didClickPanGestureRecognizer:)];
[self.navigationController.view addGestureRecognizer:panRecognizer];
}
- (void)push
{
[self.navigationController pushViewController:_nextVC animated:YES];
}
- (void)modal
{
[self presentViewController:_nextVC animated:YES completion:nil];
}
#pragma mark - UINavigationControllerDelegate iOS7新增的2個方法
// 動畫特效
- (id<UIViewControllerAnimatedTransitioning>) navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
/**
* typedef NS_ENUM(NSInteger, UINavigationControllerOperation) {
* UINavigationControllerOperationNone,
* UINavigationControllerOperationPush,
* UINavigationControllerOperationPop,
* };
*/
if (operation == UINavigationControllerOperationPush) {
return self.customAnimator;
}else{
return nil;
}
}
// 交互
- (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController*)navigationController interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController
{
/**
* 在非交互式動畫效果中,該方法返回 nil
* 交互式轉場,自我理解意思是,用戶能通過自己的動作來(常見:手勢)控制,不同于系統缺省給定的push或者pop(非交互式)
*/
return _interactionController;
}
#pragma mark - Transitioning Delegate (Modal)
// 前2個用于動畫
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
self.minToMaxAnimator.animationType = AnimationTypePresent;
return _minToMaxAnimator;
}
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.minToMaxAnimator.animationType = AnimationTypeDismiss;
return _minToMaxAnimator;
}
// 后2個用于交互
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator
{
return _interactionController;
}
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator
{
return nil;
}
以上實現的是非交互的轉場,指的是完全按照系統指定的切換機制,用戶無法中途取消或者控制進度切換.那怎么來實現交互轉場呢:
UIPercentDrivenInteractiveTransition實現了UIViewControllerInteractiveTransitioning接口的類,,可以用一個百分比來控制交互式切換的過程。我們在手勢識別中只需要告訴這個類的實例當前的狀態百分比如何,系統便根據這個百分比和我們之前設定的遷移方式為我們計算當前應該的UI渲染,十分方便。具體的幾個重要方法:
-(void)updateInteractiveTransition:(CGFloat)percentComplete 更新百分比,一般通過手勢識別的長度之類的來計算一個值,然后進行更新。之后的例子里會看到詳細的用法
-(void)cancelInteractiveTransition 報告交互取消,返回切換前的狀態
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久免费精品|
中文字幕精品av|
亚洲综合自拍一区|
亚洲美女性生活视频|
日韩一区二区三区xxxx|
国产成人免费91av在线|
欧美刺激性大交免费视频|
国产91|九色|
国模私拍一区二区三区|
中文字幕国产亚洲|
欧美激情a∨在线视频播放|
日韩精品高清视频|
欧美限制级电影在线观看|
欧美在线免费观看|
精品久久久久久久久久久|
91久久久久久久一区二区|
日韩成人黄色av|
亚洲国产日韩欧美在线图片|
亚洲欧美一区二区三区在线|
亚洲综合大片69999|
成人激情黄色网|
成人有码在线播放|
国产精品流白浆视频|
亚洲qvod图片区电影|
91大神在线播放精品|
青青a在线精品免费观看|
色哟哟网站入口亚洲精品|
欧美成人午夜激情在线|
亚洲性无码av在线|
欧美成人免费全部观看天天性色|
超在线视频97|
在线观看日韩www视频免费|
亚洲香蕉伊综合在人在线视看|
国产成人高潮免费观看精品|
日韩日本欧美亚洲|
色偷偷9999www|
日韩中文字幕av|
亚洲一区二区三区久久|
欧美www视频在线观看|
欧美成人精品h版在线观看|
97久久精品人搡人人玩|
亚洲美女又黄又爽在线观看|
国产精品爽黄69天堂a|
欧美精品在线免费|
91在线中文字幕|
亚洲自拍偷拍网址|
97久久久免费福利网址|
亚洲精品女av网站|
欧美孕妇与黑人孕交|
成人网在线观看|
久久久久久伊人|
亚洲欧美日韩视频一区|
国产欧美精品一区二区三区-老狼|
97人人做人人爱|
色综合色综合久久综合频道88|
亚洲一区二区三区乱码aⅴ|
欧美一级高清免费播放|
日韩欧美国产一区二区|
欧美日韩成人在线播放|
亚洲人成电影在线观看天堂色|
国产精品久久婷婷六月丁香|
www.欧美三级电影.com|
色综合天天综合网国产成人网|
欧美成人高清视频|
亚洲欧美国产精品va在线观看|
亚洲va久久久噜噜噜|
91久久综合亚洲鲁鲁五月天|
97超碰色婷婷|
全色精品综合影院|
黄色成人av网|
久久久久成人精品|
久久综合伊人77777蜜臀|
亚洲国产成人久久综合|
成人在线视频福利|
91香蕉嫩草神马影院在线观看|
久久欧美在线电影|
国产女人精品视频|
亚洲精品久久久久中文字幕二区|
亚洲国产成人在线视频|
欧美俄罗斯性视频|
色偷偷亚洲男人天堂|
国产精品成人观看视频国产奇米|
91精品美女在线|
亚洲福利小视频|
欧美第一页在线|
欧美成人自拍视频|
91欧美精品午夜性色福利在线|
在线观看视频亚洲|
欧美精品在线观看91|
日韩性生活视频|
欧美高清自拍一区|
91精品久久久久久久久中文字幕|
日韩电影中文 亚洲精品乱码|
国产精品第一视频|
国产精品久久一区主播|
夜夜狂射影院欧美极品|
欧美另类第一页|
欧美午夜精品久久久久久浪潮|
日韩在线观看免费全|
欧美一级大片在线免费观看|
在线播放国产一区中文字幕剧情欧美|
亚洲新中文字幕|
亚洲精品在线视频|
国产精品嫩草影院久久久|
国产日韩欧美视频|
九九热99久久久国产盗摄|
91av视频导航|
欧美激情在线播放|
2025国产精品视频|
欧美夜福利tv在线|
亚洲精品在线视频|
91精品国产九九九久久久亚洲|
欧美性xxxx极品hd欧美风情|
久久精品福利视频|
国色天香2019中文字幕在线观看|
亚洲人线精品午夜|
91地址最新发布|
亚洲片在线资源|
国产精品久久久久久久午夜|
亚洲一品av免费观看|
精品网站999www|
在线看国产精品|
日韩女在线观看|
久久久久久久久久国产精品|
国产精品精品久久久久久|
日韩在线免费观看视频|
国产精品久久久亚洲|
国产美女精彩久久|
亚洲黄页视频免费观看|
午夜精品在线视频|
97人人模人人爽人人喊中文字|
亚洲欧美综合另类中字|
日韩黄在线观看|
欧美怡红院视频一区二区三区|
欧美尤物巨大精品爽|
91亚洲一区精品|
欧美大人香蕉在线|
日韩美女视频在线观看|
欧美性生交xxxxx久久久|
一区二区在线视频|
亚洲人精品午夜在线观看|
亚洲free性xxxx护士白浆|
久久精品视频在线观看|
成人性生交大片免费观看嘿嘿视频|
在线激情影院一区|
久久福利视频网|
日韩av网站大全|
激情懂色av一区av二区av|
日韩精品极品在线观看|
国产偷亚洲偷欧美偷精品|
欧美大片免费观看在线观看网站推荐|
伦理中文字幕亚洲|
2020国产精品视频|
久久久这里只有精品视频|
人人澡人人澡人人看欧美|
欧美激情二区三区|
欧美日韩国产精品专区|
欧美激情精品久久久久久黑人|
国产精品视频26uuu|
www日韩中文字幕在线看|
亚洲aa中文字幕|
欧美视频在线视频|
欧美一区第一页|
欧美精品久久久久久久|