b2cloud

23rd July 2013

Vertically aligning a UILabel

Guides | Tutorial By 3 years ago

Horizontally aligning a UILabel in iOS is easy enough, but unfortunately vertically isn’t as simple. There are many ways to achieve vertically aligned text, each with their pros and cons. I’m going to go through a few methods, and then show my preferred method for vertically aligned text.

Using a UITextField

Primarily used for text input, the UITextField conveniently subclasses UIControl, which gives the ability to vertically align straight out of the box. The downside to this is you are now stuck with a UITextField and all the behaviour that comes with it. To get it to do what you want you will need to turn editing off, plus it’s slightly slower than a straight UILabel.

Using a UITextView

This only works for top alignment (the only vertical alignment UITextView supports without fiddling around). This one is probably worse than UITextField as as well as being editable, the view has padding around the edges that makes things more difficult.

Reframing the UILabel

The big plus here is the low overhead of the UILabel. This is usually the way to go if you are also laying out content around the label that depends on how large the text is inside. However, a lot of the calculations are going to be the same, and sometimes a simple vertical alignment property is desired.

Subclassing the UILabel

This is what I will demonstrate below. The only real downside is that you need to subclass to take advantage of any new behaviour, which may be annoying if you’re working with older code and need to inject this between existing classes (check out method swizzling for this).

First the header, just a simple subclass and property. I will reuse the UIControlContentVerticalAlignment enum from UIControl.

#import 

@interface VALabel : UILabel

@property (nonatomic, assign) UIControlContentVerticalAlignment verticalAlignment;

@end

And the implementation. When the vertical alignment is changed the label is marked for redraw. Before redrawing, the frame is manipulated if needed to align to top or bottom.

#import "VALabel.h"

@implementation VALabel

@synthesize verticalAlignment;

#pragma mark -
#pragma mark Super

- (void) drawTextInRect:(CGRect)rect
{
	if(verticalAlignment == UIControlContentVerticalAlignmentTop ||
	   verticalAlignment == UIControlContentVerticalAlignmentBottom)
	{
		//	If one line, we can just use the lineHeight, faster than querying sizeThatFits
		const CGFloat height = ((self.numberOfLines == 1) ? ceilf(self.font.lineHeight) : [self sizeThatFits:self.frame.size].height);
		
		if(height < self.frame.size.height)
			rect.origin.y = ((self.frame.size.height - height) / 2.0f) * ((verticalAlignment == UIControlContentVerticalAlignmentTop) ? -1.0f : 1.0f);
	}

	[super drawTextInRect:rect];
}

#pragma mark -
#pragma mark Self

- (void) setVerticalAlignment:(UIControlContentVerticalAlignment)_verticalAlignment
{
	verticalAlignment = _verticalAlignment;

	[self setNeedsDisplay];
}

@end

That's it. The final VALabel class can be downloaded here.

Recommended Posts

Yammer integrations in ReactJS

Post by 3 years ago

I am writing this blog while I am working on a project for our client’s intranet website. The client requires the website has the ability to share, like and write comments in the website through

Got an idea?

We help entrepreneurs, organizations and established brands from around
the country bring ideas to life. We would love to hear from you!