上一章寫了不可交互的自定義轉(zhuǎn)場動(dòng)畫忆绰,這一章寫寫可交互的自定義轉(zhuǎn)場動(dòng)畫,先來效果圖可岂。
進(jìn)入正題
可交互轉(zhuǎn)場主要依賴于UIPercentDrivenInteractiveTransition這個(gè)類错敢,顧名思義百分比推動(dòng)互動(dòng)轉(zhuǎn)場。
第一步:我們首先要聲明變量缕粹,并初始化
@property (nonatomic,strong)UIPercentDrivenInteractiveTransition *interactive;
self.interactive = [[UIPercentDrivenInteractiveTransition alloc]init];
第二步:創(chuàng)建手勢
-(void)Pan:(UIPanGestureRecognizer *)recognizer{
CGPoint translatedPoint = [recognizer translationInView:self.view];
CGFloat persent = translatedPoint.x / [[UIScreen mainScreen]bounds].size.width;
persent = fabs(persent);
switch (recognizer.state) {
case UIGestureRecognizerStateBegan:{
self.isClickPush = NO;
[self.navigationController popViewControllerAnimated:YES];
break;
}
case UIGestureRecognizerStateChanged:{
//手勢過程中稚茅,通過updateInteractiveTransition設(shè)置pop過程進(jìn)行的百分比
[self.interactive updateInteractiveTransition:persent];
break;
}
case UIGestureRecognizerStateEnded:{
//手勢完成后結(jié)束標(biāo)記并且判斷移動(dòng)距離是否過半,過則finishInteractiveTransition完成轉(zhuǎn)場操作致开,否者取消轉(zhuǎn)場操作
if (persent > 0.5) {
[self.interactive finishInteractiveTransition];
}else{
[self.interactive cancelInteractiveTransition];
}
break;
}
default:
break;
}
}
第三步:在代理中實(shí)現(xiàn)
需要注意的是:我們是在另外一個(gè)界面進(jìn)行的自定義轉(zhuǎn)場峰锁,那么我們的Navigation的協(xié)議也需要遵循我們當(dāng)前界面的協(xié)議萎馅。我相信聰明的老鐵會(huì)意識(shí)到一個(gè)問題双戳,我們控制器所用到Navigation都是使用的同一個(gè),那我在當(dāng)前界面修改了Navigation的協(xié)議糜芳,當(dāng)我返回到上一層界面時(shí)飒货,Navigation的協(xié)議是否會(huì)有錯(cuò)誤魄衅。答案是肯定會(huì)有的。那就是導(dǎo)致下一次轉(zhuǎn)場動(dòng)畫失效塘辅,如下圖:
既然知道了問題所在晃虫,那么寫起來就方便多了,我們只需要在兩個(gè)界面的viewDidApper中實(shí)現(xiàn)代理方法就可以了
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.isClickPush = YES;
self.navigationController.delegate = self;
}
第四步:在代理中實(shí)現(xiàn)方法
#pragma mark 自定義轉(zhuǎn)場動(dòng)畫
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
if (operation == UINavigationControllerOperationPop) {
return self.animatedTransitioning;//你設(shè)置的動(dòng)畫
}
return nil;
}
#pragma mark 交互自定義轉(zhuǎn)場動(dòng)畫的代理方法
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController{
if (self.isClickPush) {
return nil;
}else{
return self.interactive;
}
}
寫到這里的話其實(shí)已經(jīng)大公告成啦扣墩,但是有老鐵會(huì)注意到self.isClickPush出現(xiàn)了多次哲银,他的用意何在呢?其實(shí)如果在這里不注意的話呻惕,那就掉到了一個(gè)大坑里面去了荆责。首先我來說說我對(duì)Navigation的兩個(gè)代理方法的理解吧。
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController
這兩個(gè)方法是在程序要進(jìn)行轉(zhuǎn)場之前運(yùn)行的亚脆,深入點(diǎn)的話:當(dāng)程序進(jìn)行轉(zhuǎn)場之前做院,無論你是自定義轉(zhuǎn)場動(dòng)畫,還是可交互的自定義轉(zhuǎn)場動(dòng)畫濒持,亦或是系統(tǒng)自帶的轉(zhuǎn)場键耕,統(tǒng)統(tǒng)都會(huì)先跑這兩個(gè)方法。
既然知道了這個(gè)柑营,我們也不難發(fā)現(xiàn)了屈雄,如果我們使用navigation自帶的返回按鈕返回上一層的話,也會(huì)運(yùn)行這兩個(gè)代理方法官套,如果不加self.isClickPush進(jìn)行判斷的話棚亩,那就會(huì)直接return self.interactive導(dǎo)致程序Crash。而通過判斷return nil實(shí)際也就是使用系統(tǒng)自身的轉(zhuǎn)場了虏杰。
我這里寫了一個(gè)小小的示例代碼:老鐵們可以跟著代碼邊看邊敲邊理解讥蟆。鏈接:https://github.com/HYDupup/AnimatedTransition--
另外我自己寫封裝一個(gè)開源的代碼,包含了幾種有意思的酷炫且實(shí)用的轉(zhuǎn)場動(dòng)畫纺阔,操作簡單瘸彤,只需引入頭文件,并在UIViewControllerAnimatedTransitioning代理中初始化就OK啦笛钝。
鏈接:https://github.com/HYDupup/YDAnimatedTransition质况,內(nèi)附效果圖和使用方法,如果好用的話請(qǐng)幫我點(diǎn)個(gè)Star哦玻靡。直接在Podfile添加pod 'YDAnimatedTransition'也可以哦~
如果各位有什么有趣的酷炫的轉(zhuǎn)場設(shè)計(jì)结榄,也可以在下面留言信柿,我可以和大家一起實(shí)現(xiàn)舶赔,