Two common techniques for making a visually appealing app are a liberal use
of masking and shadows, e.g. masking an image to be a circle or have round
corners, or adding a drop shadow to images or text to give them more
depth. Both of these techniques are pretty trivial in iOS on their own, but
are a bit of a intellectual leap to combine them at the same time. This post
will hopefully lessen that leap.
To summarize the technique we’re going to use, we’re going to mask the
image into a circle using its layer property, then add that layer to a
new container layer that will also shadow the image, and then add that container
layer with the masked and shadowed image as a sublayer of our view.
Initially we just start with an image as a subview of our view with no
modifications other than centering it.
//// TJViewController.m// MaskAndShadow//// Created by Travis Jeffery on 2012-08-06.// Copyright (c) 2012 Travis Jeffery. All rights reserved.//#import "TJViewController.h"@interfaceTJViewController()@end@implementationTJViewController-(void)viewDidLoad{[superviewDidLoad];// white bg to see the shadow easierself.view.backgroundColor=[UIColorwhiteColor];// the image we're going to mask and shadowUIImageView*image=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"sj.jpeg"]];image.center=self.view.center;[self.viewaddSubview:image];}-(void)viewDidUnload{[superviewDidUnload];// Release any retained subviews of the main view.}-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{if([[UIDevicecurrentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone){return(interfaceOrientation!=UIInterfaceOrientationPortraitUpsideDown);}else{returnYES;}}@end
Then we manipulate our image into a circle by rounding and masking its
corners.
//// TJViewController.m// MaskAndShadow//// Created by Travis Jeffery on 2012-08-06.// Copyright (c) 2012 Travis Jeffery. All rights reserved.//#import "TJViewController.h"@interfaceTJViewController()@end@implementationTJViewController-(void)viewDidLoad{[superviewDidLoad];// white bg to see the shadow easierself.view.backgroundColor=[UIColorwhiteColor];// the image we're going to mask and shadowUIImageView*image=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"sj.jpeg"]];image.center=self.view.center;// use the image's layer to mask the image into a circleimage.layer.cornerRadius=roundf(image.frame.size.width/2.0);image.layer.masksToBounds=YES;[self.viewaddSubview:image];}-(void)viewDidUnload{[superviewDidUnload];// Release any retained subviews of the main view.}-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{if([[UIDevicecurrentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone){return(interfaceOrientation!=UIInterfaceOrientationPortraitUpsideDown);}else{returnYES;}}@end
Since our shadow will also be masked if we just tried to add to the image as it
is now, we add the masked image’s layer to an unmasked container layer that
will also add shadow the image, and then we add that container layer with the
masked and shadowed image as a sublayer of our view.
//// TJViewController.m// MaskAndShadow//// Created by Travis Jeffery on 2012-08-06.// Copyright (c) 2012 Travis Jeffery. All rights reserved.//#import "TJViewController.h"#import <QuartzCore/QuartzCore.h>@interfaceTJViewController()@end@implementationTJViewController-(void)viewDidLoad{[superviewDidLoad];// white bg to see the shadow easierself.view.backgroundColor=[UIColorwhiteColor];// the image we're going to mask and shadowUIImageView*image=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"sj.jpeg"]];image.center=self.view.center;// make new layer to contain shadow and masked imageCALayer*containerLayer=[CALayerlayer];containerLayer.shadowColor=[UIColorblackColor].CGColor;containerLayer.shadowRadius=10.f;containerLayer.shadowOffset=CGSizeMake(0.f,5.f);containerLayer.shadowOpacity=1.f;// use the image's layer to mask the image into a circleimage.layer.cornerRadius=roundf(image.frame.size.width/2.0);image.layer.masksToBounds=YES;// add masked image layer into container layer so that it's shadowed[containerLayeraddSublayer:image.layer];// add container including masked image and shadow into view[self.view.layeraddSublayer:containerLayer];}-(void)viewDidUnload{[superviewDidUnload];// Release any retained subviews of the main view.}-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{if([[UIDevicecurrentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone){return(interfaceOrientation!=UIInterfaceOrientationPortraitUpsideDown);}else{returnYES;}}@end