前兩天阔拳,寫了一篇關于切換圖片推拉效果的文章崭孤,在總結的時候發(fā)現(xiàn)還有一點沒有提到,就是當頁面跳轉時候的動畫糊肠,很多APP現(xiàn)在不滿足于系統(tǒng)自帶的效果辨宠,所以要重寫動畫,上篇中著重提到更靈活的使用scrollView货裹,和一般動畫比例的用法彭羹。而這篇著重說下如何重寫系統(tǒng)動畫。老規(guī)矩泪酱,先上圖:
相信有不少人都用過boss直聘,當然还最,我也是突然來靈感砌左,就用這個效果粘衬。
首先,需要一個collectionView。初始化康聂,并吧cell封裝出來,便于復用時的控制(這里由于資源有限胖翰,cell內(nèi)容就不變了荧缘,如果想改變,可以把內(nèi)容傳進來枣氧,在set方法里改變本cell的內(nèi)容)
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(kScreenSize.width - 20, 155);
layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
layout.minimumLineSpacing = 10;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, kScreenSize.width, kScreenSize.height - 64) collectionViewLayout:layout];
_collectionView.delegate = self;
_collectionView.dataSource = self;
[_collectionView registerClass:[CoustomCollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
_collectionView.backgroundColor = [UIColor groupTableViewBackgroundColor];
[self.view addSubview:_collectionView];
接下來溢十,封裝cell,在這里就不在上代碼了达吞,并給cell添加跳轉事件张弛。
封裝cell之后,才是重頭戲。
首先我們需要知道UIViewControllerAnimatedTransitioning協(xié)議吞鸭,這個協(xié)議的實現(xiàn)就是負責切換的具體內(nèi)容寺董,當然可以理解為“在切換中發(fā)生了什么”。在這個協(xié)議里面有兩個方法:
- -(NSTimeInterval)transitionDuration: transitionContext:
- -(void)animateTransition: transitionContext
第一個方法即為跳轉的時間刻剥,便是navgationBar變化的時間遮咖,第二個方法便是所要執(zhí)行的動畫,在這里造虏,有一個泛型為UIViewControllerContextTransitioning對象御吞,第二個方法里,傳入的參數(shù)只有這一個酗电,可想而知魄藕,跳轉過程中的所有東西,可能都是這一個對象控制的撵术。
通過API可知背率,在這個對象里,有from的頁面和to的頁面嫩与,還有控制頁面的對象寝姿,這樣,我們就好辦了划滋,通過這個對象饵筑,添加動畫效果即可,如果是老手处坪,不必多說根资,但是,對于新手同窘,我們就必須講一下這個對象中的containerView玄帕。
containerView便是控制整個跳轉的頁面,便是我們在跳轉中和跳轉后所顯示的內(nèi)容頁想邦。官方文檔是這樣描述的:“這個視圖即是動畫發(fā)生的地方”裤纹,沒錯,通俗易懂丧没,跳轉視圖鹰椒,這個視圖是必須控制好的。
下面就上代碼:
-(void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
//獲取到containerView視圖
UIView *containerView = [transitionContext containerView];
//獲取到目的視圖(同樣可以獲取目的控制器和根源控制器)
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
//獲取到根源視圖
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *backView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, kScreenSize.width, kScreenSize.height-64)];
backView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
UIView *sizeView = [[UIView alloc] initWithFrame:_frame];
sizeView.backgroundColor = [UIColor whiteColor];
// _isGO為變量呕童,判斷用戶使用的是push還是pop
// 動畫處理
if (_isGo) {
[containerView addSubview:backView];
[containerView addSubview:sizeView];
[UIView animateWithDuration:0.3 animations:^{
fromView.transform = CGAffineTransformScale(fromView.transform, 0.9, 0.9);
backView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
sizeView.frame = CGRectMake(0, 64, kScreenSize.width, kScreenSize.height);
} completion:^(BOOL finished) {
[backView removeFromSuperview];
[sizeView removeFromSuperview];
toView.frame = CGRectMake(0, 0, kScreenSize.width, kScreenSize.height);
[containerView addSubview:toView];
[transitionContext completeTransition:YES];
}];
}];
}else{
[containerView insertSubview:toView belowSubview:fromView];
backView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[containerView insertSubview:backView belowSubview:fromView];
[UIView animateWithDuration:0.5 animations:^{
fromView.frame = CGRectMake(0, -kScreenSize.height, kScreenSize.width, kScreenSize.height);
}completion:^(BOOL finished) {
[backView removeFromSuperview];
[UIView animateWithDuration:0.3 animations:^{
toView.transform = CGAffineTransformMakeScale(1, 1);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}];
}
動畫寫完了漆际,跳轉問題也了,如何讓跳轉時走此方法夺饲,這就涉及到nav的代理了灿椅,代理中有這個方法:
-(nullable id <UIViewControllerAnimatedTransitioning>)navigationController: animationControllerForOperation: fromViewController:toViewController:
這個方法返回的就是動畫套蒂,即我們剛剛實現(xiàn)的實現(xiàn)協(xié)議的類。
-(nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC{
if (operation == UINavigationControllerOperationPush) {
_animation.isGo = YES;
}else{
_animation.isGo = NO;
}
return _animation;
}
這就是完成了自定義跳轉動畫
當然茫蛹,還有人會用到presentViewCotroller操刀,presentViewController動畫實現(xiàn)都一樣,當時代理時需要UIViewControllerTransitioningDelegate協(xié)議調(diào)用secondVC.transitioningDelegate = self婴洼;
代理中有兩個方法骨坑,一個是跳轉,還有一個是退回
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:presentingController:sourceController:
同樣返回自定義動畫類即可