iOS Recipes - Matt Drance [59]
Recipe 30 Curl the Page to a New View
Problem
Simulating a page turn is a popular visual technique, often used in book- or magazine-reading apps. Creating a realistic effect, such as the one used in iBooks, requires detailed knowledge of OpenGL. Is it possible to create a similar effect using only the higher-level Core Animation APIs?
Solution
The Core Animation APIs encompass a great deal of functionality including layer manipulation and various styles of animation, but hidden in their depths is a relatively unknown feature called sublayer transformation. We’ve shown in several recipes how you can transform a layer in many ways—through scaling, rotation, and translation. Sublayer transformation gives us the same level of control but over the entire layer hierarchy. If you combine this technique with rotations that take into account depth in the z-axis, you can effectively control objects in a 3D space. This is the technique we will use to implement our transition (see Figure 34, A partial page curl transition ).
We first need to split the transitioning view into a series of layer strips; by making use of the PRPCompositedView category, we can ensure that the view and any subviews it may have get composited into a single image before we break it into strips.
We also need to create a second set of layers the same size as the image strips but initially without any contents so they will be completely transparent. We attach this set of strips as sublayers to our transforming layer. Each of these strips is added with an incrementing amount of rotation and translation applied, effectively creating a multisided tube. If we were to look at this tube in cross section, the center point of the multisided shape would match the center point of the parent layer. By using sublayer transformation, rotating the parent layer will result in the tube rotating about its center. If we simultaneously animate the tube from one side of the screen to the other while gradually replacing the contents of the strips with the image strips of the original view, it will appear as if the view is curling away from the background.
Figure 34. A partial page curl transition
* * *
It’s probably worth running the sample app at this point to get a sense of how the transition works, but we will need to dig into the code to really understand the mechanics of the process.
The viewWithView class method creates the instance of the PRPViewTransition class and uses the PRPCompositedView category to composite the specified view with its subViews into a single image that can be split into the requested number of strips.
ViewTransition/PRPViewTransition.m
+ (PRPViewTransition *) viewWithView:(UIView *)view splitInto:(int)parts {
PRPViewTransition *tempView = [[PRPViewTransition alloc]
initWithFrame:view.frame];
tempView.numLayers = parts;
[tempView cutLayersFromImage:[view PRPCompositeView]];
return [tempView autorelease];
}
The transition view initially acts as a static copy of the original view that it replaces and needs to be at the front of the main view hierarchy. When the MainViewController adds it to the view, the didMoveToSuperview delegate method is called. At this point we can start the transition process by creating the rotating tube of layers and then starting the switching animation process.
ViewTransition/PRPViewTransition.m
- (void)didMoveToSuperview {
[self createRotatingLayers];
[self SwitchLayers];
}
The numLayers property directly affects the size of the strips we create, and the transition effect can be made to look quite different by specifying different values. A high number creates quite narrow strips, resulting