Online Book Reader

Home Category

iOS Recipes - Matt Drance [55]

By Root 241 0
of depth to any view simply by including a shadow, and in most cases that addition is all you need to produce the desired effect. But what if you want to render a shadow that doesn’t follow the shape of the image in the view, perhaps to imply the angle of the source of light or to render the shape of the ground the shadow is passing over. How can you modify the shadow’s shape to create these or similar effects?

Solution

You can define a CALayer to display a shadow that follows its nontransparent shape, offset from the image contents, to give the effect of the view being shown in relief, set apart from the background. Apple introduced a new property in iOS 3.2 that defines a shadowPath. This path does not need to follow the shape of the CALayer contents, so we can be a little more creative and go beyond the default relief shadow. In this case, we will build a cloud image that appears to cast its flattened shadow on the ground as it floats across the screen.

GraphicsGarden/PRPCloud.m

- (void)drawRect:(CGRect)rect {

CGFloat fullHeight = self.bounds.size.height;

CGPoint top = CGPointMake(0, 0);

CGPoint bottom = CGPointMake(0, fullHeight);

UIBezierPath *pPath = [self CreatePathWithHeight:

self.bounds.size.height];

[pPath addClip];

CGGradientRef gradient = [self gradientWithColor:self.innerColor

toColor:self.outerColor

count:2];

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextDrawLinearGradient(context,

gradient,

top,

bottom,

0);

pPath.lineWidth = self.lineThickness;

[self.strokeColor setStroke];

[pPath stroke];

pPath = [self CreatePathWithHeight:self.bounds.size.height/2.0];

self.layer.shadowPath = pPath.CGPath;

if (!self.shadowDistance) shadowDistance = self.bounds.size.height*1.8;

self.alpha = 0.9;

self.layer.shadowOffset = CGSizeMake(0, self.shadowDistance);

self.layer.shadowOpacity = 0.4;

}

PRPCloud is a subclass of PRPShapedView and therefore follows the same pattern as all the simple view objects in the Graphics Garden application. In the drawRect method, we build our cloud image using a UIBezierPath that is created in CreatePathWithHeight (shown next) from a C array of relative points. The CreatePathWithHeight method uses the height parameter to adjust the position of the points as the path is built.

GraphicsGarden/PRPCloud.m

- (UIBezierPath *) CreatePathWithHeight:(CGFloat)h {

CGFloat w = self.bounds.size.width;

CGFloat points[] =

{

0.4, 0.2,

0.5, 0.1, 0.6, 0.2,

0.8, 0.2, 0.8, 0.4,

0.9, 0.5, 0.8, 0.6,

0.8, 0.8, 0.6, 0.8,

0.5, 0.9, 0.4, 0.8,

0.2, 0.8, 0.2, 0.6,

0.1, 0.5, 0.2, 0.4,

0.2, 0.2, 0.4, 0.2,

};

CGPoint point;

CGPoint cPoint;

UIBezierPath *pPath = [UIBezierPath bezierPath];

point = CGPointMake(points[0]*w, points[1]*h);

[pPath moveToPoint:point];

for (int i = 2; i < sizeof(points)/sizeof(float); i+=4) {

cPoint = CGPointMake(points[i]*w, points[i+1]*h);

point = CGPointMake(points[i+2]*w, points[i+3]*h);

[pPath addQuadCurveToPoint:point controlPoint:cPoint];

}

[pPath closePath];

return pPath;

}

Consequently, we need to call the CreatePathWithHeight in two places—first to create the path for the cloud and then for the shadowPath property but with half the original height. The shadowOffset of the layer is set to the value of the shadowDistance property of the cloud view, placing it far enough below the cloud to give the impression that it’s at ground level.

You could also create a shadow using an additional CALayer, but that would require the extra step of synchronizing the position of the two layers whenever you needed to move or animate them.

Recipe 28 Display Animated Views

Problem

You can use Core Graphics to create a series of UIImageViews that represent various stages of a moving object. How do you display them in sequence to create a looping animation?

Solution

We’ve addressed animation in some detail in the recipes in this section, working mostly with manipulating the position or rotation of layers. Classic cell animation, like the kind seen in cartoons, uses a different technique that involves displaying a sequence

Return Main Page Previous Page Next Page

®Online Book Reader