Online Book Reader

Home Category

iOS Recipes - Matt Drance [53]

By Root 235 0
initWithFrame:flowerRect];

UIImage *compositeFlower = [flower PRPCompositeView];

[flower release];

for (int i = 0; i < 60; i++) {

int size = height/12;

CGFloat flowerSize = arc4random()%size+size;

CGRect flowerRect = CGRectMake(arc4random()%(int)width*0.9,

arc4random()%pos+2*pos ,

flowerSize*0.7,

flowerSize);

UIImageView *compView = [[UIImageView alloc] initWithFrame:flowerRect];

compView.image = compositeFlower;

compView.layer.zPosition = flowerRect.origin.y+flowerSize;

[self.view addSubview:compView];

[compView release];

[self growUp:compView forDuration:arc4random()%100/25.0+4];

}

We can then build out our scene by creating UIImageViews based on our new image. With each flower being a single entity, they can be individually animated, which wouldn’t have been possible had it still been a hierarchy of UIViews.

Here’s the code for the category method we need to composite our image from multiple UIViews:

GraphicsGarden/UIView+PRPCompositedView.m

UIGraphicsBeginImageContextWithOptions(self.layer.bounds.size, NO, 0);

[self.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *compoundImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return compoundImage;

The CALayer method renderInContext is key, because it renders all sublayers into the graphics context, effectively flattening our hierarchy into a single element. The C method UIGraphicsGetImageFromCurrentImageContext uses the bitmap data from the graphics context and builds the new UIImage.

By using rotation transformation, we avoid the need to create more complex components for our image. Compositing our UIViews into a single UIImage allows us to reduce memory usage, increase performance, and animate the flower.

Recipe 26 Animate a Gradient Layer

Problem

Adding background gradients can greatly improve the presentation of a view that would otherwise be rendered in a single solid color. But you want to go further and give your gradients a dynamic element to indicate a change of state or to show that the app is responding to user input.

Solution

The CALayer family of classes has grown in the last few releases of iOS, pulling in many of the classes previously found only in Mac OS X. With iOS 3.0, Apple introduced CAGradientLayer, making it easy for you to generate a graduated background for any UIView. The greatest advantage of using this class comes from the animatable properties, which can create extremely fast, hardware-based effects. Animation even extends to the arrays of colors used to build the gradients, so you can create a smooth, interpolated, cross-fade of gradients (see Figure 31, Animated gradient layer ). The only downside of CAGradientLayer is that currently you can use only an axial, or linear, gradient.[3]

Figure 31. Animated gradient layer

* * *

Using this technique yields a nicely animated opening fade-in of a multicolored graduated background, demonstrated in the context of the Graphics Garden sample app. You could apply this to create an animated sunrise-sunset effect, for example.

Although we are using CAGradientLayer, we add our code to a UIView subclass. That may not seem intuitive, but remember that each UIView is backed by a CALayer, and by overriding the layerClass method we can ensure this view is backed by a CAGradientLayer.

GraphicsGarden/GradientView.m

+ (Class)layerClass {

return [CAGradientLayer class];

}

Overriding the layerClass method is a technique more often used for OpenGL-backed UIViews, but it works just as well for creating the gradient-backed UIView we need here.

First we set up the initial color array to reflect how we want the gradient to look at the end of the animation. This code initializes the values that fix the three main colors to their relative positions in the UIView to give the overall effect we want. Without these control values, the generated gradient would have the colors spaced evenly throughout the layer.

GraphicsGarden/GradientView.m

- (void)didMoveToSuperview {

self.backgroundColor = [UIColor blackColor];

Return Main Page Previous Page Next Page

®Online Book Reader