One of the least talked about feature deficiencies of Apple iPhone SDK Font Handling is the inability to underline text.
You know – like you see in every web link on every web page on the internet.
Yeah. That.
For me, where I need this the most is when I’m trying to create a link on one of my text sections or display elements, that will invoke a web URI and go off to do some work.
There isn’t a way to style underline fonts included with the iPhone, and Apple doesn’t make it easy at all to include custom fonts without a great deal of pain and gnashing of teeth.
What is one to do?
Well, I don’t know what the rest of you guys do, but this is what I did.
I created a button class (UnderlineButton) that subclasses UIButton and implemented my own drawRect function to draw the underline myself.
This isn’t rocket science, but works quite nicely. The button should probably have a number of init functions to do things like set underline stroke width and color, but I needed a quick and dirty solution and had about 30 minutes to write, test, and deliver.
The code below is what I wound up with (UnderlineButton.m
follows; UnderlineButton.h
is simply a stub class that contains only @interface UnderlineButton : UIButton {}
).
// // UnderlineButton.m // // Created by David Hinson on 11/24/09. // Copyright 2009 Sumner Systems Management, Inc.. All rights reserved. // #import "UnderlineButton.h"
@implementation UnderlineButton
- (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // Initialization code } return self; } - (void)drawRect:(CGRect)rect { [super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 62.0/255.0, 62.0/255.0, 62.0/255.0, 1.0); // Draw them with a 1.0 stroke width. CGContextSetLineWidth(context, 1.0); // Draw a single line from left to right CGContextMoveToPoint(context, 0, rect.size.height); CGContextAddLineToPoint(context, rect.size.width, rect.size.height); CGContextStrokePath(context); }
- (void)dealloc { [super dealloc]; }
@end
To use the button in an actual application, you would do something like the following:
CGSize constraintSize, offset1;
constraintSize.width = 300.0f;
constraintSize.height = MAXFLOAT;
NSString * btnText = @"My Button Text";
UnderlineButton * myButton = [[UnderlineButton buttonWithType:UIButtonTypeCustom] retain];
offset1 = [btnText sizeWithFont:[UIFont systemFontOfSize:16]
constrainedToSize:constraintSize
lineBreakMode:UILineBreakModeTailTruncation];
myButton.frame = CGRectMake(20, 164, offset1.width, offset1.height);
[myButton setTitle:btnText forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
[myButton setFont:[UIFont systemFontOfSize:16]];
[myButton addTarget:self action:@selector(doButtonTouch:)
forControlEvents:UIControlEventTouchUpInside];
[cell myButton];
[myButton release];
The doButtonTouch
method will perform whatever it is you want to do; in my case this invoking another method to slide in a UIWebView to show drill down content.
Summary: Underline Text. Nothing there to make it natively easy, but workable solutions can be cobbled together.
But I will be the very first to say “it shouldn’t be this hard.“