側(cè)滑的轉(zhuǎn)場實(shí)現(xiàn)

學(xué)習(xí)了seedante大神的《iOS 視圖控制器轉(zhuǎn)場詳解》https://github.com/seedante/iOS-Note/wiki/ViewController-Transition,覺得iOS的自定義轉(zhuǎn)場功能十分強(qiáng)大,可以實(shí)現(xiàn)許多絢麗的動畫效果。seedante大神的博客中代碼是用的Swift語言編寫的,此文中介紹的側(cè)滑效果用ObjectiveC實(shí)現(xiàn),關(guān)鍵性的地方有參考該文章。

在學(xué)習(xí)轉(zhuǎn)場之前首先要理清楚轉(zhuǎn)場中的一些關(guān)鍵詞:

1.轉(zhuǎn)場代理(Transition Delegate):自定義轉(zhuǎn)場的第一步便是提供轉(zhuǎn)場代理,告訴系統(tǒng)使用我們提供的代理而不是系統(tǒng)的默認(rèn)代理來執(zhí)行轉(zhuǎn)場。有如下三種轉(zhuǎn)場代理,對應(yīng)上面三種類型的轉(zhuǎn)場:

UINavigationControllerDelegate //UINavigationController 的 delegate 屬性遵守該協(xié)議。

UITabBarControllerDelegate //UITabBarController 的 delegate 屬性遵守該協(xié)議。

UIViewControllerTransitioningDelegate //UIViewController 的 transitioningDelegate 屬性遵守該協(xié)議。

這里除了UIViewControllerTransitioningDelegate是 iOS 7 新增的協(xié)議,其他兩種在 iOS 2 里就存在了,在 iOS 7 時(shí)擴(kuò)充了這兩種協(xié)議來支持自定義轉(zhuǎn)場。轉(zhuǎn)場發(fā)生時(shí),UIKit 將要求轉(zhuǎn)場代理將提供轉(zhuǎn)場動畫的核心構(gòu)件:動畫控制器和交互控制器(可選的);由我們實(shí)現(xiàn)。

2.動畫控制器(Animation Controller):最重要的部分,負(fù)責(zé)添加視圖以及執(zhí)行動畫;遵守UIViewControllerAnimatedTransitioning協(xié)議;由我們實(shí)現(xiàn)。

3.交互控制器(Interaction Controller):通過交互手段,通常是手勢來驅(qū)動動畫控制器實(shí)現(xiàn)的動畫,使得用戶能夠控制整個(gè)過程;遵守UIViewControllerInteractiveTransitioning協(xié)議;系統(tǒng)已經(jīng)打包好現(xiàn)成的類供我們使用。

4.轉(zhuǎn)場環(huán)境(Transition Context):提供轉(zhuǎn)場中需要的數(shù)據(jù);遵守UIViewControllerContextTransitioning協(xié)議;由 UIKit 在轉(zhuǎn)場開始前生成并提供給我們提交的動畫控制器和交互控制器使用。

5.轉(zhuǎn)場協(xié)調(diào)器(Transition Coordinator):可在轉(zhuǎn)場動畫發(fā)生的同時(shí)并行執(zhí)行其他的動畫,其作用與其說協(xié)調(diào)不如說輔助,主要在 Modal 轉(zhuǎn)場和交互轉(zhuǎn)場取消時(shí)使用,其他時(shí)候很少用到;遵守UIViewControllerTransitionCoordinator協(xié)議;由 UIKit 在轉(zhuǎn)場時(shí)生成,UIViewController 在 iOS 7 中新增了方法transitionCoordinator()返回一個(gè)遵守該協(xié)議的對象,且該方法只在該控制器處于轉(zhuǎn)場過程中才返回一個(gè)此類對象,不參與轉(zhuǎn)場時(shí)返回 nil。

結(jié)合這張圖:

下面是用交互轉(zhuǎn)場實(shí)現(xiàn)的側(cè)滑效果。

相較于一般的非交互轉(zhuǎn)場,交互轉(zhuǎn)場在UIViewControllerTransitioningDelegate協(xié)議里面多實(shí)現(xiàn)了一下兩個(gè)方法:

- (nullable id )interactionControllerForPresentation:(id )animator;

-(nullable id )interactionControllerForDismissal:(id )animator;

用來返回一個(gè)UIViewControllerInteractiveTransitioning交互控制器,該類可以控制轉(zhuǎn)場過程的進(jìn)度,在使用中,只需返回一個(gè)UIPercentDrivenInteractiveTransition對象即可。該對象通過以下幾個(gè)方法來控制轉(zhuǎn)場過程的進(jìn)度:

- (void)updateInteractiveTransition:(CGFloat)percentComplete;

- (void)cancelInteractiveTransition;

-(void)finishInteractiveTransition;

調(diào)用第一個(gè)成員方法需要給它一個(gè)進(jìn)度的參數(shù),告訴代理此轉(zhuǎn)場應(yīng)該進(jìn)度一個(gè)多少,一般可以將此函數(shù)加入到手勢里面調(diào)用。后面兩個(gè)方法,可以直接調(diào)用,完成的結(jié)果和非交互的轉(zhuǎn)場效果一樣。

以下是在UIScreenEdgePanGestureRecognizer手勢里面調(diào)用:

-(void)handleAction:(UIScreenEdgePanGestureRecognizer *)gesture

{

?? ? CGFloat translationX = [gesture translationInView:_bottomVc.view].x;

? ? CGFloat translationBase = _bottomVc.view.frame.size.width;

? ? CGFloat translationAbs = translationX > 0 ? translationX : -translationX;

? ? CGFloat percent = translationAbs > translationBase ? 1.0:translationAbs/translationBase;

?? ? if (gesture.state == UIGestureRecognizerStateBegan) {

? ? ? ? ?[_bottomVc presentViewController:self.navigation animated:YES completion:nil];

? ? ?}

? ? ? ?if (gesture.state == UIGestureRecognizerStateChanged) {

? ? ? ? ? ? ? ? ? ? ?[self.interaction updateInteractiveTransition:percent];

? ? ? ? ?}

? ? ? ? ?if (gesture.state == UIGestureRecognizerStateEnded) {

? ? ? ? if (percent > 0.5) {

? ? ? ? ? [self.interaction finishInteractiveTransition];

? ? ? ? ?}? ? ? ? else

? ? ? ? ? ? ? [self.interaction cancelInteractiveTransition];

? ? ? ? ? ? NSLog(@"%@",_bottomVc.view);

? ? ? ?}}

轉(zhuǎn)場的代理設(shè)置如下:

_navigation.modalPresentationStyle = UIModalPresentationCustom;

_navigation.transitioningDelegate = self;

在使用UIModalPresentationCustom模式進(jìn)行轉(zhuǎn)場的時(shí)候有一個(gè)注意點(diǎn),就是在UIViewControllerAnimatedTransitioning動畫控制器中實(shí)現(xiàn)代理方法?- (void)animateTransition:(id )transitionContext;時(shí),當(dāng)用UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];來獲得fromView,在轉(zhuǎn)場進(jìn)入的時(shí)候,會為空。所以要使用[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];在返回控制器的View。(注意,在轉(zhuǎn)場出現(xiàn)和轉(zhuǎn)場退出的時(shí)候,fromView和toVc是互換的,但是在轉(zhuǎn)場退出時(shí),fromView還是會為空)。

我們可以在類中設(shè)置一個(gè)成員變量來保持上下文UIViewControllerContextTransitioning,在

-(void)animationEnded:(BOOL)transitionCompleted

{

NSLog(@"toView %@",[_context viewForKey:UITransitionContextToViewKey]);

NSLog(@"fromView %@",[_context viewForKey:UITransitionContextFromViewKey]);

NSLog(@"toVc %@",[_context viewControllerForKey:UITransitionContextToViewControllerKey]);

NSLog(@"fromVc %@",[_context viewControllerForKey:UITransitionContextFromViewControllerKey]);

NSLog(@"toView--vc %@",[_context viewControllerForKey:UITransitionContextToViewControllerKey].view);

NSLog(@"fromView--vc %@",[_context viewControllerForKey:UITransitionContextFromViewControllerKey].view);

}

可以看不同調(diào)用方式的情況。

在轉(zhuǎn)場完成和轉(zhuǎn)場退出后,之前的presentedView會丟失,為了在側(cè)滑時(shí)可用同時(shí)顯示兩個(gè)界面,在轉(zhuǎn)場動畫中應(yīng)該設(shè)置一個(gè)靜態(tài)的UIView用來保存presentingView的父視圖,在[toVc isBeingPresented]的條件下,我們進(jìn)行一個(gè)保存presentingView = fromView.superview;然后在動畫完成時(shí)添加[presentingView addSubview:fromView];,在[fromVc isBeingDismissed]的條件下,動畫完成時(shí)應(yīng)該這樣添加

BOOL isCancel = [transitionContext transitionWasCancelled];

?if (!isCancel) {

[presentingView addSubview:toView];

[fromView removeFromSuperview]; }

最后,代碼請到我的Github里面下載,里面還實(shí)現(xiàn)了幾個(gè)非交互轉(zhuǎn)場的方式,都是基于ObjectiveC語言的,歡迎大家交流學(xué)習(xí)。

Github:??https://github.com/AirChen/ACTransition

下面這個(gè)是以側(cè)滑為基礎(chǔ),模仿QQ的側(cè)滑效果:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言的前言 唐巧前輩在微信公眾號「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各項(xiàng)指標(biāo)...
    VincentHK閱讀 5,580評論 3 44
  • 在iOS中隨處都可以看到絢麗的動畫效果,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,697評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,271評論 5 13
  • iOS視圖控制器詳解 視圖控制器中的視圖顯示在屏幕上有兩種方式:最主要的方式是內(nèi)嵌在容器控制器中,比如 UINav...
    coder_feng閱讀 11,367評論 2 12
  • 前言 正如標(biāo)題所示,iOS開發(fā)中, 自定義轉(zhuǎn)場的過渡動畫確實(shí)是必須要了解的, 在iOS7之后實(shí)現(xiàn)也是很簡單的. 如...
    ZeroJ閱讀 9,198評論 9 122

友情鏈接更多精彩內(nèi)容