Posted on January 3, 2010 at 10:21pm EST. More.

Draw your own Disclosure Indicator

I’m writing Cocoa Touch code to draw a button which, when pressed, pushes a new view controller onto the stack. If I was working with a UITableView, I’d simply set the cell’s accessory to be a disclosure indicator (the little gray arrowhead) and call it a day.

But I’m not working with table cells, so even though the standard disclosure indicator is perfect for this situation, if I want one I’ll have to draw it myself.

In this situation I will usually take a screenshot of the real iPhone control, add the image file to my project, and then feel kind of guilty about it. I began to do this, but I realized that the disclosure indicator is really only two gray lines. Two lines! How hard can it be to just draw it in code?

It turns out that it’s not too hard, if you’re willing to spend some time experimenting with different numbers and seeing what looks right. Fortunately for you, I’ve saved you the trouble by posting the answer here:

// Draws a disclosure indicator such that the tip of the arrow is at (x,y)
void BRDrawDisclosureIndicator(CGContextRef ctxt, CGFloat x, CGFloat y) {
    static const CGFloat R = 4.5; // "radius" of the arrow head
    static const CGFloat W = 3; // line width
    CGContextMoveToPoint(ctxt, x-R, y-R);
    CGContextAddLineToPoint(ctxt, x, y);
    CGContextAddLineToPoint(ctxt, x-R, y+R);
    CGContextSetLineCap(ctxt, kCGLineCapSquare);
    CGContextSetLineJoin(ctxt, kCGLineJoinMiter);
    CGContextSetLineWidth(ctxt, W);

Before calling the function, you should set the stroke color to 50% gray if you’re drawing on a white background or white if the control is highlighted and you’re drawing on a blue background. Or, you can use whatever color you like.

To be honest, I only eyeballed the result, so it might not be a pixel-perfect reproduction of the real thing. However, I think my eyeballs are at least as good as most users' eyeballs, so I will confidently declare this code Good Enough.