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.