Recently at work while I was designing some user interface elements, I found that to make the elements look correct for iOS 6 you need to either indent, or emboss them; For instance the buttons on the iOS keyboard are embossed.

This requires two lots of shadows, there is a very obvious shadow at the bottom of each of the buttons, and there is also a white shadow running across the top. This is much more obvious on the darker grey buttons. To get the same effect on your own drawing you either need to draw a white line across the top of embossed elements, or set things up so there is a white shadow generated across the top of the element.

We can overide the drawRect: method of a UIView subclass to draw something that looks like a keyboard button. First let’s create a path to make a rounded rect (we will reuse this path again later):

Next we need to get the context that we are going to draw with and set it up to draw a button. Before setting up the context we should save its state that way at the end of the drawRect method we can restore its state, and any changes that we’ve made to the context won’t be passed on.

Finally we need to make the inside shadow. We will use the Non-zero winding rule (see the Filling a Path section of the Quartz2D Programming Guide) to fill only areas that our outside of the path. To do this we will make a new path in the context by drawing a closed rect in an anti-clockwise direction around the outside of our shape (which was drawn in a clockwise direction). We will then add the original path to the path for the rect, and fill the shape.

Another approach would be to try and draw a path exactly arround the outside of our shape. There are a couple of drawbacks to doing this. Firstly if the shape is complicated, or contains any holes in the middle then it may take some time to work out and code the paths that you need to draw. Secondly because you aren’t using the same path as your original shape (you’re drawing a line at half lines width away), there may be small differeces in which pixels are drawn at the edge, this may result in aliasing effects.

So here is the result of all of the work that we have done:

As well as making items appear above the surface we can quickly use the same code to embed things into a surface. With a few minor changes we can make this:

This is made with a photo of my door, son, and the code above (although I’m not sure if a photo of the code above will do a lot of good). To draw a inner shadow in a layer like this is a lot of work. In the next post I plan to give a more general solution to this problem.

You can find the source for this code here.