ios開發——經典翻頁庫Leaves源碼解析

來源:互聯網
上載者:User

ios開發——經典翻頁庫Leaves源碼解析

在做文本app的時候經常會用到翻頁效果,我瞭解的翻頁效果有三種。最基本的是用transition動畫的CurlDown和CurlUp來實現,這種實現非常簡單,但是不能控制過程。然後是類似開源庫Leaves提供的方法一樣,可以控制中間過程,不過只能左右水平翻頁。再者就是apple的iBooks以及目前大多數電子書應用都能實現的“最真實的翻頁”,不但可以水平控制,而且可以有“折角”,效果也很流暢。

第三種的實現難度略大,暫且不提,這裡一起看一下經典的Leaves庫,這個庫的代碼寫得非常清晰易懂,適合初學者學習。


代碼結構:


Leaves代碼遵循MVC設計模式。LeavesCache是model,主要功能是獲得當前頁圖片、緩衝某一頁圖片以及對資料的清空等操作。LeavesView是View,主要是展示平常狀態下以及翻頁過程中的映像、層等內容,是接下來詳細研究的類。LeavesViewController是Controller,一般當我們整個視圖都是LeavesView時我們可以繼承這個控制器,這個控制器已經將dataSource設為自己,所以我們只需重寫dataSource協議方法即可。


<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+TGVhdmVzQ2FjaGXA4KO6PC9wPgo8cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20141012/201410120913426.png" alt="\">


其中pageSize指每一頁的大小,在view中被設定為self.bounds。dataSource為資料來源。




載入圖片的方法是,定義一個字典pageCache用來儲存已經被載入過的映像,每次需要擷取圖片時從這裡面擷取,如果為nil,則說明或者是第一次載入,或者已經被刪掉了,需要調用私人方法imageForPageIndex:來重新擷取。



該方法中用Quartz2D來截取螢幕獲得圖片,這裡返回的是CGImageRef,目的是方便為圖層的contents賦值。

有了這兩個操作,剩下的就簡單了,主要就是調用這兩個方法進行載入、預先載入、清空等。



而最後的minimizeToPageIndex:方法,正如其注釋:Uncache all pages except previous, current, and next(除去當前頁、前一頁和後一頁以外其餘全部清除),目的是節省空間的,在View中每次翻到某一頁即調用該方法。


LeavesView:

在LeavesView的標頭檔中對每個屬性和方法都做了詳盡的注釋,比如點擊進入下一頁的間距targetWidth,是否支援預先載入的backgroundRendering等。關鍵是實現檔案中的一些私人屬性的理解:


關於其中各種層和陰影的理解,都體現在接下來的方法initCommon中,該方法是初始化這些層並為其設定基本屬性的方法:

- (void)initCommon {self.clipsToBounds = YES;    //最頂層_topPage = [[CALayer alloc] init];_topPage.masksToBounds = YES;_topPage.contentsGravity = kCAGravityLeft;_topPage.backgroundColor = [[UIColor whiteColor] CGColor];    //翻頁過程中的最頂層_topPageOverlay = [[CALayer alloc] init];_topPageOverlay.backgroundColor = [[[UIColor blackColor] colorWithAlphaComponent:0.2] CGColor];    //翻頁過程中壓在上一頁上的陰影層_topPageShadow = [[CAGradientLayer alloc] init];_topPageShadow.colors = [NSArray arrayWithObjects:(id)[[[UIColor blackColor] colorWithAlphaComponent:0.6] CGColor],(id)[[UIColor clearColor] CGColor],nil];    //映射的起止點,類比PS裡漸層的滑鼠開始點與鬆開點_topPageShadow.startPoint = CGPointMake(1,0.5);_topPageShadow.endPoint = CGPointMake(0,0.5);        //書頁背面的一層_topPageReverse = [[CALayer alloc] init];_topPageReverse.backgroundColor = [[UIColor whiteColor] CGColor];_topPageReverse.masksToBounds = YES;    //書背面顯示倒影圖片的一層_topPageReverseImage = [[CALayer alloc] init];_topPageReverseImage.masksToBounds = YES;_topPageReverseImage.contentsGravity = kCAGravityRight;    //書背面頁的最頂層_topPageReverseOverlay = [[CALayer alloc] init];_topPageReverseOverlay.backgroundColor = [[[UIColor whiteColor] colorWithAlphaComponent:0.8] CGColor];    //書背面頁的陰影層_topPageReverseShading = [[CAGradientLayer alloc] init];_topPageReverseShading.colors = [NSArray arrayWithObjects:(id)[[[UIColor blackColor] colorWithAlphaComponent:0.6] CGColor],(id)[[UIColor clearColor] CGColor],nil];_topPageReverseShading.startPoint = CGPointMake(1,0.5);_topPageReverseShading.endPoint = CGPointMake(0,0.5);    //下一頁的一層_bottomPage = [[CALayer alloc] init];_bottomPage.backgroundColor = [[UIColor whiteColor] CGColor];_bottomPage.masksToBounds = YES;    //壓在下一頁上的陰影層_bottomPageShadow = [[CAGradientLayer alloc] init];_bottomPageShadow.colors = [NSArray arrayWithObjects:   (id)[[[UIColor blackColor] colorWithAlphaComponent:0.6] CGColor],   (id)[[UIColor clearColor] CGColor],   nil];_bottomPageShadow.startPoint = CGPointMake(0,0.5);_bottomPageShadow.endPoint = CGPointMake(1,0.5);[_topPage addSublayer:_topPageShadow];[_topPage addSublayer:_topPageOverlay];[_topPageReverse addSublayer:_topPageReverseImage];[_topPageReverse addSublayer:_topPageReverseOverlay];[_topPageReverse addSublayer:_topPageReverseShading];[_bottomPage addSublayer:_bottomPageShadow];[self.layer addSublayer:_bottomPage];[self.layer addSublayer:_topPage];[self.layer addSublayer:_topPageReverse];_leafEdge = 1.0;//表示出於未翻頁狀態        _backgroundRendering = NO;_pageCache = [[LeavesCache alloc] initWithPageSize:self.bounds.size];}

其中用到了CoreAnimation的相關知識,比如普通層CALayer,控制色彩坡形的CAGradientLayer等。

初始化完成以後便可以在layoutSubview方法中為其設定位置和填充資料,這裡分別抽成了兩個方法:

- (void)setLayerFrames {self.topPage.frame = CGRectMake(self.layer.bounds.origin.x,                self.layer.bounds.origin.y,                                         self.leafEdge * self.bounds.size.width,               self.layer.bounds.size.height);        self.topPageReverse.frame = CGRectMake(self.layer.bounds.origin.x + (2*self.leafEdge-1) * self.bounds.size.width, self.layer.bounds.origin.y, (1-self.leafEdge) * self.bounds.size.width,self.layer.bounds.size.height);        self.bottomPage.frame = self.layer.bounds;        self.topPageShadow.frame = CGRectMake(self.topPageReverse.frame.origin.x - 40, 0, 40, self.bottomPage.bounds.size.height);        self.topPageReverseImage.frame = self.topPageReverse.bounds;self.topPageReverseImage.transform = CATransform3DMakeScale(-1, 1, 1);        self.topPageReverseOverlay.frame = self.topPageReverse.bounds;        self.topPageReverseShading.frame = CGRectMake(self.topPageReverse.bounds.size.width - 50, 0, 50 + 1,self.topPageReverse.bounds.size.height);        self.bottomPageShadow.frame = CGRectMake(self.leafEdge * self.bounds.size.width, 0, 40, self.bottomPage.bounds.size.height);        self.topPageOverlay.frame = self.topPage.bounds;}

剛讀到這裡的時候可能會對self.leafEdge的控制感到迷惑,到了touch相關方法的時候就能瞭解了。

設定圖片的方法:


有了這兩個輔助方法,就可以在layoutSubview方法中完成基本介面了



接下來還有兩個值得注意的地方,其餘的均為輔助方法了。

一個是對頁數的控制,即self.currentPageIndex。currentPageIndex仿照數組,是從0開始的。而且重寫了setter:


也就是說每次設定currentPageIndex都要重新設定圖片,所以設定currentPageIndex的原則是:如果是上一頁,則直接設定,因為對於上一頁而言,本頁面正好是bottomLayer對應的層,而對於下一頁,只有當完全翻頁以後才能設定currentPageIndex,否則圖片就不相符了。說起來抽象,具體看代碼:



touchesBegin:withEvent:方法


touchesEnded:withEvent:方法




還有一個問題就是在touch過程中對leafEdge的控制


這樣就可以實現對層的位置(見上述方法)、以及層陰影的透明度等進行控制了。


可以在touchesMoved方法中列印一下leafEdge,這樣可以直觀的看到該屬性是如何控制這些的。


LeavesViewController:

這個控制器就沒什麼特別的了,僅僅是將LeavesView添加到了視圖中並設定了代理,抽象實現了方法而已



通過這種方法的話可以想象那種完美的翻頁效果該如何?:在touchesMove方法中通過計算判斷移動方向,然後再對層位置、陰影位置等做出調整 - -"| 想想就覺得複雜。。。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.