iOS 實(shí)現(xiàn)自定義頁面跳轉(zhuǎn)(一)

現(xiàn)在的app很少只有一個(gè)頁面的丽蝎,在不同頁面間的跳轉(zhuǎn)成為了iOS開發(fā)人員需要知道的技術(shù)點(diǎn)。UIKit 中已經(jīng)為我們實(shí)現(xiàn)了一些系統(tǒng)自帶的頁面跳轉(zhuǎn)方法霎桅,但是程序員這種充滿腦洞的特殊人群怎么能夠只滿足于那些不fashion的跳轉(zhuǎn)呢巾钉?因此本著您可將自己累死也要讓用戶酷炫(不爽瘫镇?)的態(tài)度沽一,我們還是很有必要去知道如何實(shí)現(xiàn)一個(gè)自定義的頁面跳轉(zhuǎn)的盖溺。

一, UINavigationController 和 present view controller

在學(xué)習(xí)自定義頁面跳轉(zhuǎn)之前铣缠,我們可以先了解一下UIKit已經(jīng)為我們實(shí)現(xiàn)的頁面跳轉(zhuǎn)方法烘嘱。當(dāng)然已經(jīng)清楚的同學(xué)可以往下看了。
首先我們需要明白的一點(diǎn)是蝗蛙,UINavigationController其實(shí)是一種 Container View Controller

Container view controllers are a way to combine the content from multiple view controllers into a single user interface. Container view controllers are most often used to facilitate navigation and to create new user interface types based on existing content. Examples of container view controllers in UIKit include UINavigationController, UITabBarController, and UISplitViewController, all of which facilitate navigation between different parts of your user interface.

從上面的定義我們可以明白以下三點(diǎn)
一蝇庭,Container view controller 是用來將多個(gè)view controller中的內(nèi)容結(jié)合到同一個(gè)用戶交互界面的。
二捡硅,Container view controller可以很方便的進(jìn)行頁面導(dǎo)航并且基于已有的內(nèi)容創(chuàng)建新的頁面交互類型哮内。
三,UINavigationController, UITabBarController, and UISplitViewController這些在UIKit中的類都屬于Container view controller壮韭。


接下來讓我們看看UINavigationViewController的一般用法

##創(chuàng)建 UINavigationViewController并設(shè)置root view controller
UIViewController *vc = [[UIViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; 
self.window.rootViewController = nav;
##通過push跳轉(zhuǎn)頁面
UIViewController *viewController = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
##通過pop跳轉(zhuǎn)頁面
[self.navigationController popViewControllerAnimated:YES];
UINavigationController

在這里我們大概應(yīng)該明白北发,navigation controller通過一個(gè)數(shù)組來維護(hù)加入的view controller纹因,并實(shí)現(xiàn)了棧的原理來push和pop已經(jīng)在數(shù)組中的view controller。


以下兩個(gè)實(shí)例方法屬于UIViewController鲫竞,通過以下兩個(gè)實(shí)例方法可以很方便的實(shí)現(xiàn)跳轉(zhuǎn)辐怕。

- (void)presentViewController:(UIViewController *)viewControllerToPresent 
                     animated:(BOOL)flag 
                   completion:(void (^)(void))completion;
- (void)dismissViewControllerAnimated:(BOOL)flag 
                           completion:(void (^)(void))completion;

二逼蒙,A Custom Present Transition & A Custom Dismiss Transition

對(duì)于一個(gè)自定義的跳轉(zhuǎn)來說我們首先要明白跳轉(zhuǎn)都做了些什么从绘?

  • 規(guī)范跳轉(zhuǎn)發(fā)生所需的時(shí)間和跳轉(zhuǎn)時(shí)所需的交互方法
  • 提供具體的交互方法對(duì)象,也就是實(shí)現(xiàn)一個(gè)交互方法提供給系統(tǒng)跳轉(zhuǎn)時(shí)調(diào)用

清楚了以上兩點(diǎn)我們就比較好理解以下兩個(gè)我們需要實(shí)現(xiàn)的協(xié)議了

UIViewControllerTransitioningDelegate的定義

An object that implements the UIViewControllerTransitioningDelegate protocol vends the objects used to manage a fixed-length or interactive transition between view controllers. When you want to present a view controller using a custom modal presentation type, set its modalPresentationStyle property to UIModalPresentationCustom and assign an object that conforms to this protocol to its transitioningDelegate property. When you present that view controller, UIKit queries your transitioning delegate for the objects to use when animating the view controller into position.

UIViewControllerAnimatedTransitioning的定義

Adopt the UIViewControllerAnimatedTransitioning protocol in objects that implement the animations for a custom view controller transition. The methods in this protocol let you define an animator object, which creates the animations for transitioning a view controller on or off screen in a fixed amount of time. The animations you create using this protocol must not be interactive. To create interactive transitions, you must combine your animator object with another object that controls the timing of your animations.

以上的定義我就不再翻譯了是牢,相信通過或者沒通過四級(jí)考試的你都是可以看懂的僵井。??

協(xié)議與View Controller之間的關(guān)系

** 從上面的關(guān)系圖我們可以明白不同模塊之間的關(guān)系,首先需要有一個(gè)UIViewController類去實(shí)現(xiàn)UIViewControllerTransitioningDelegate驳棱。UIViewControllerTransitioningDelegate會(huì)從Animation Controller獲得一個(gè)交互對(duì)象批什,Animation Controller通過實(shí)現(xiàn)UIViewControllerAnimatedTransitioning協(xié)議來提供交互,Transitioning Context對(duì)象實(shí)現(xiàn)UIViewContextTransitioning協(xié)議社搅,通過Transitioning Context我們可以獲得有關(guān)view controller的上下文信息驻债。**

好了,不寫代碼講解的程序員都是耍流氓形葬,讓我們開始耍流氓吧合呐!??

1, 實(shí)現(xiàn)一個(gè)animator object
#import <Foundation/Foundation.h>
//敲黑板1
@interface BouncePresentAnimationController : NSObject<UIViewControllerAnimatedTransitioning>

@end
#import "BouncePresentAnimationController.h"

@implementation BouncePresentAnimationController
//敲黑板2
-(NSTimeInterval) transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
    return 1.0;
}

//敲黑板3
-(void) animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    //敲黑板4
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    CGRect finalFrame = [transitionContext finalFrameForViewController:toViewController];
    
    //敲黑板5
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    
    //敲黑板6
    UIView *containerView = [transitionContext containerView];
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    toViewController.view.frame = CGRectOffset(finalFrame, 0, screenBounds.size.height);
    [containerView addSubview:toViewController.view];
    
    NSTimeInterval duration = [self transitionDuration:transitionContext];
    
    //敲黑板7
    [UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
        fromViewController.view.alpha = 0.5;
        toViewController.view.frame = finalFrame;
    } completion:^(BOOL finished){
     fromViewController.view.alpha = 1.0;
     [transitionContext completeTransition:YES];
        }
    ];
}

@end

1, 創(chuàng)建一個(gè)實(shí)現(xiàn)動(dòng)畫的類繼承自NSObject并且實(shí)現(xiàn)UIViewControllerAnimatedTransitioning協(xié)議笙以。
2淌实,實(shí)現(xiàn)transitionDuration方法,這個(gè)方法UIKit會(huì)自動(dòng)調(diào)用這個(gè)方法來獲得跳轉(zhuǎn)動(dòng)畫所需的時(shí)間猖腕。我們?cè)诤竺鎸@式調(diào)用這個(gè)方法拆祈。
3, 實(shí)現(xiàn)animateTransition方法倘感,UIKit會(huì)掉用這個(gè)方法放坏,這個(gè)方法將告訴動(dòng)畫對(duì)象如何實(shí)現(xiàn)我們所需的動(dòng)畫效果。
4老玛, 通過transitionContext獲得toViewController,toViewController是我們將要顯示的視圖控制器淤年。
5,通過transitionContext獲得fromViewController逻炊,fromViewController是我們?cè)谶M(jìn)行跳轉(zhuǎn)前正在顯示的視圖控制器互亮。
6,通過transitionContext獲得containerView,containerView是進(jìn)行動(dòng)畫跳轉(zhuǎn)的容器余素。我們需要將toViewController.view加入這個(gè)containerView,這樣toViewController.view將被加入視圖結(jié)構(gòu)中豹休。我們才能在跳轉(zhuǎn)之后顯示這個(gè)view。
7桨吊,UIView的動(dòng)畫方法來實(shí)現(xiàn)跳轉(zhuǎn)動(dòng)畫威根。

toView&fromView

上面這幅圖描述了在presentation和dismissal這兩個(gè)跳轉(zhuǎn)過程中頁面對(duì)應(yīng)的關(guān)系凤巨。有興趣的同學(xué)可以查看

2,實(shí)現(xiàn)UIViewControllerTransitioningDelegate

接下來我們需要在進(jìn)行頁面跳轉(zhuǎn)的view controller中實(shí)現(xiàn)UIViewControllerTransitionsingDelegate協(xié)議,并且將要跳轉(zhuǎn)顯示的toViewController.transitioningDelegate = self.
在這里我們需要實(shí)現(xiàn)一個(gè)UIViewControllerTransitioningDelegate方法洛搀。

-(id<UIViewControllerAnimatedTransitioning>) animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
    return _bouncePresentAnimationController;
}

在這里敢茁,UIKit在頁面跳轉(zhuǎn)的時(shí)候掉用以上的方法,我們?cè)谶@里返回一個(gè)我們已經(jīng)實(shí)現(xiàn)并且創(chuàng)建的動(dòng)畫對(duì)象留美,UIKit通過這個(gè)已經(jīng)實(shí)現(xiàn)的動(dòng)畫對(duì)象完成頁面跳轉(zhuǎn)過程中的動(dòng)畫效果彰檬。

3,如何實(shí)現(xiàn)頁面dismissal

其實(shí)頁面的消失也是一樣的道理,通過實(shí)現(xiàn)以上所提到的兩個(gè)協(xié)議我們就可以實(shí)現(xiàn)相關(guān)的動(dòng)畫效果了谎砾。有興趣的同學(xué)可以看Demo逢倍。

三,參考內(nèi)容

1,《iOS 7 By Tutorials》
2, UIViewControllerTransitioningDelegate
3, UIViewControllerAnimatedTransitioning
4, View Controller Programming Guide for iOS

這篇文章主要是對(duì)于自定義頁面跳轉(zhuǎn)的基本概念介紹和基本使用方法景图,下一片文章將講解如何實(shí)現(xiàn)可進(jìn)行用戶界面互動(dòng)的自定義頁面跳轉(zhuǎn)并且實(shí)現(xiàn)一個(gè)UIPresentationController子類來實(shí)現(xiàn)頁面跳轉(zhuǎn)的封裝较雕。

歡迎大家閱讀指正,如果喜歡請(qǐng)不吝點(diǎn)贊挚币!??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亮蒋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子妆毕,更是在濱河造成了極大的恐慌慎玖,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件设塔,死亡現(xiàn)場(chǎng)離奇詭異凄吏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)闰蛔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門痕钢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人序六,你說我怎么就攤上這事任连。” “怎么了例诀?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵随抠,是天一觀的道長。 經(jīng)常有香客問我繁涂,道長拱她,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任扔罪,我火速辦了婚禮秉沼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己唬复,他們只是感情好矗积,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敞咧,像睡著了一般棘捣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上休建,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天乍恐,我揣著相機(jī)與錄音,去河邊找鬼丰包。 笑死禁熏,一個(gè)胖子當(dāng)著我的面吹牛壤巷,可吹牛的內(nèi)容都是我干的邑彪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼胧华,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼寄症!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矩动,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤有巧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后悲没,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篮迎,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年示姿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了甜橱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栈戳,死狀恐怖岂傲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情子檀,我是刑警寧澤镊掖,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站褂痰,受9級(jí)特大地震影響亩进,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缩歪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一归薛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦苟翻、人聲如沸韵卤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沈条。三九已至,卻和暖如春诅炉,著一層夾襖步出監(jiān)牢的瞬間蜡歹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工涕烧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留月而,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓议纯,卻偏偏與公主長得像父款,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瞻凤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容