Ios development-Analysis of Leaves source code in the classic paging Library

Source: Internet
Author: User

Ios development-Analysis of Leaves source code in the classic paging Library

Page flip is often used in text apps. I know three types of page flip effects. The most basic is to use the CurlDown and CurlUp of the transition animation. This implementation is very simple, but cannot control the process. Then, similar to the method provided by the open-source library Leaves, the intermediate process can be controlled, but the pages can only be turned horizontally. Furthermore, apple's iBooks and the "most real page flip" that most e-book applications can achieve at present can not only be horizontally controlled, but also be "broken", and the effect is also smooth.

The third implementation is a little more difficult, so we will not mention it for the moment. Let's take a look at the Classic Leaves library. The code in this library is very clear and easy to understand, and is suitable for beginners to learn.


Code structure:


Leaves Code follows the MVC design pattern. LeavesCache is a model. Its main function is to obtain the current page image, cache a page image, and clear data. LeavesView is a View that displays images, layers, and other content in the normal state and during page turning. LeavesViewController is a Controller. Generally, when the entire view is LeavesView, We can inherit this Controller. This Controller has set dataSource as our own, so we only need to override the dataSource protocol method.


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


PageSize indicates the size of each page, which is set to self. bounds in view. DataSource is the data source.




The method for loading an image is to define a dictionary pageCache to store the already loaded image. It is obtained from this dictionary each time you need to obtain the image. If it is nil, it indicates that the image is loaded for the first time, alternatively, you must call the private method imageForPageIndex: to retrieve it again.



In this method, Quartz2D is used to capture the screen and obtain the image. CGImageRef is returned to facilitate the assignment of contents of the layer.

With these two operations, the rest is simple. The two methods are called for loading, pre-loading, and clearing.



The last minimizeToPageIndex: method, as its comment: Uncache all pages failed t previous, current, and next (all except the current page, the previous page, and the next page ), the purpose is to save space. This method is called every time a page is displayed in the View.


LeavesView:

Each attribute and method is annotated in the header file of LeavesView. For example, you can click the targetWidth distance on the next page to see whether pre-loaded backgroundRendering is supported. The key is to understand some private attributes in the file:


The understanding of various layers and shadows is reflected in the following method initCommon. This method is used to initialize these layers and set basic attributes for them:

-(Void) initCommon {self. clipsToBounds = YES; // top-level _ topPage = [[CALayer alloc] init]; _ topPage. masksToBounds = YES; _ topPage. contentsGravity = kCAGravityLeft; _ topPage. backgroundColor = [[UIColor whiteColor] CGColor]; // top-level _ topPageOverlay = [[CALayer alloc] init] During page turning; _ topPageOverlay. backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0.2] CGColor]; // shadow layer on the previous page during page turning process _ topPageShadow = [[CAGradientLayer alloc] init]; _ topPageShadow. colors = [NSArray arrayWithObjects :( id) [[[UIColor blackColor] colorWithAlphaComponent: 0.6] CGColor], (id) [[UIColor clearColor] CGColor], nil]; // the start and end of the ing, which is similar to the gradient Mouse start point and release point _ topPageShadow in PS. startPoint = CGPointMake (1, 0.5); _ topPageShadow. endPoint = CGPointMake (0, 0.5); // layer _ topPageReverse = [[CALayer alloc] init]; _ topPageReverse. backgroundColor = [[UIColor whiteColor] CGColor]; _ topPageReverse. masksToBounds = YES; // layer _ topPageReverseImage = [[CALayer alloc] init]; _ topPageReverseImage. masksToBounds = YES; _ topPageReverseImage. contentsGravity = kCAGravityRight; // top-level _ topPageReverseOverlay = [[CALayer alloc] init]; _ topPageReverseOverlay. backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent: 0.8] CGColor]; // shadow layer _ 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); // layer _ bottomPage = [[CALayer alloc] init]; _ bottomPage. backgroundColor = [[UIColor whiteColor] CGColor]; _ bottomPage. masksToBounds = YES; // shadow layer on the next page _ 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: _ blank]; [_ topPageReverse addSublayer: _ topPageReverseOverlay]; [_ topPageReverse addSublayer: _ blocks]; [_ bottomPage addSublayer: _ bottomPageShadow]; [self. layer addSublayer: _ bottomPage]; [self. layer addSublayer: _ topPage]; [self. layer addSublayer: _ topPageReverse]; _ leafEdge = 1.0; // indicates that the status is not paging. _ backgroundRendering = NO; _ pageCache = [[LeavesCache alloc] initWithPageSize: self. bounds. size];}

The knowledge of CoreAnimation is used, for example, normal layer CALayer, and CAGradientLayer that controls the color gradient.

After initialization, you can set the location and fill in data in the layoutSubview method. Here, two methods are extracted:

- (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;}

When I read this article, I may be confused about the control of self. leafEdge, and I will be able to understand the touch-related methods.

How to set the image:


With these two auxiliary methods, you can complete the basic interface in the layoutSubview method.



There are two points worth noting next, and the rest are auxiliary methods.

One is the control of the number of pages, that is, self. currentPageIndex. CurrentPageIndex is modeled as an array and starts from 0. In addition, the setter is rewritten:


That is to say, You need to reset the image every time you set currentPageIndex. Therefore, the principle of setting currentPageIndex is: If it is the previous page, it is set directly, because for the previous page, this page is exactly the layer corresponding to the bottomLayer, for the next page, you can set currentPageIndex only after the page is completely turned. Otherwise, the image does not match. Abstract:



TouchesBegin: withEvent: Method


TouchesEnded: withEvent: Method




Another problem is leafEdge Control During touch.


In this way, you can control the layer position (see the preceding method) and the transparency of the layer shadow.


You can print leafEdge in the touchesMoved method, so that you can intuitively see how this attribute controls this.


LeavesViewController:

This controller is nothing special. It just adds LeavesView to the view and sets a proxy to abstract and implement the method.



In this way, we can imagine how to achieve the perfect page turning effect: In the touchesMove method, we can determine the moving direction through computation, then adjust the layer position and shadow position.-"| think about the complexity...

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.