Playing with shadows with Core Animation

Happy New Year!

It has been a long time since my last article. I have been thinking about writing this for a while, but I’ve been super busy doing other things. Anyway, this post is going to be about shadows and shadow properties, what each of them means and how we should be playing with them.

I feel this is more of an article for beginner iOS programmers. When I started iOS development back in 2013 (iOS 6 FTW),  among the first things I had to do in order to get accustomed with the platform were mostly concerning UI.  The process is pretty simple: the designer sends you some mocks and you start  writing the code to build up the app, that should look exactly like the photos he/she sent. Most of my problems as a beginner, although I still bump into this at times, were concerning shadows.

Problems arose not only from the fact that they were harder to notice (I don’t know about others, but I don’t really have the visual acuity to see a shadow with a 25% opacity and 1 blur radius), but also because the SDK and documentation do not provide quite a well detailed description of what each shadow property should do. Some of them are self-explanatory, but others need a bit of digging in order to be gotten right. There are some places you might find explanations of each, but I feel they’re scattered everywhere and most of them are not very clear. This post is going to focus on the second issue and will try to gather all the information in one place with some graphic examples. Also – this article will focus on building shadows with Core Animation – not Core Graphics and DEFINITELY NOT improvisations using UIView objects as subviews to act like shadows.

So, let’s get started… Firstly, in order to implement shadows using Core Animation, we need to address the layer property of the UIView class. What is a CALayer? The documentation describes it as “An object that manages image-based content and allows you to perform animations on that content“, more specifically to our article – “has visual attributes that can be set, such as a background color, border, and shadow“. Basically, it is an information object, which describes how the view should behave during an animation, but also how to display itself.

Let’s discuss about each shadow property of the layer object in turn. Before explaining each property, I would like to underline the fact that the shadow is conceptually a curve having the properties described below, being attached to the view that embeds the given layer.

Shadow Color: this is pretty self explanatory. As the documenation describes it, it defaults to an opaque black, cannot be composed of pattern colors and is animatable. What’s important to remember is that it is a CGColor object, and not a  UIColor one. Keep in mind that simply setting this property will not show anything, as the shadow opacity (described below) also needs to be set.

Shadow Opacity: this is also quite clear – represents how opaque the shadow should be. It defaults to 0. It is a Float normalized between 0 and 1, and setting values outside the range will yield undefined behaviour. Also animatable.

– Shadow Offset: the comments in the CALayer class as well as the original Apple documentation say nothing except this property represents the offset of the shadow, that it is a CGSize and that it defaults to (0.0, -3.0). How should one take this explanation? Well, for starters – offset represents the amount something is displaced with from a base value. Moreover, I believe that the fact that this is a CGSize might be confusing. The only logical reason for this is the need of a structure that can comprise both the x and y axis offset values. Thus, this shadow offset object is nothing else than the position of the shadow relative to the view. It is also animatable. Breaking it down: if the width > 0.0, the shadow will be moved to the right, else to the left. If the height > 0.0, will be moved to the bottom, else to the top.

Shadow Radius: the comments say “the blur radius used to create the shadow” and defaults to 3. Not quite clear for someone reading this for the first time, as in the case for the shadow offset. Basically, to create the shadow effect, a blur effect is applied to the shadow curve. In short it would indicate how strong the blur effect it is, hence affecting how large the shadow would be. A more detailed explanation of the blur radius can be found here. This property is also animatable.

– Shadow Path: the code comments describe the way property works, rather than what it is. I will not dwell into that, I will explain what this property is. The path is the underlying curve the shadow follows. By default, the shadow path will be formed from a CGRect equal to the frame of the given view. One can build a shadow path of any size and of any shape – which will be visible while in bounds, or outside of bounds if the masksToBounds property is false.

These are the shadow properties we need to be playing with while designing. The following images describe applying and changing the properties and probably best reflect the use of each of them.

Shadow Color – Red shadow
Shadow Color – Green Shadow
Shadow Offset – (-10.0, -10.0)
Shadow Path – default – offset height set to view height, blur removed, in order to display the shape
Shadow Radius – default (3.0)
Shadow Radius – 0.0
Shadow Radius – 10.0
Shadow Offset – (10.0, 10.0)
Shadow Path – set to a random shape – blur removed
Shadow Opacity – 0.5

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: