Dynamically sizing UILabel

March 23rd, 2011
#ui

I use the below category when working with dynamic content. It has useful methods for setting up a UILabel frame based upon its content and restrictions that you place on it.

.h

@interface UILabel(Size)

/* 
 @method Adjusts UILabel's frame to begin at defined x and y position and have a dynamic height
 @param startX - value that the frames x coord to be
 @param startY - value that the frames y coord to be
 */
-(void)setUpMultiLineFrameWithStartXPosition:(CGFloat)startX withStartYPosition:(CGFloat)startY;

/*
 @method Adjusts UILabel's frame to begin at defined x position, to maxiumum width and height, centered veritcally based on maxHeight and height of content 
 @param width - value that the frames width property will be
 @param startX - value that the frames x coord to be
 @param maxHeight - value that the frames height property will be
 */
-(void)setUpMultiLineFrameBasedOnWidth:(CGFloat)width withStartXPosition:(CGFloat)startX withHeight:(CGFloat)maxHeight; 

/*
 @method Adjusts UILabel's frame to begin at defined x and y position, to maxiumum width and have a dynamic height
 @param maxWidth - value that the frames width property will be
 @param startX - value that the frames x coord to be
 @param startY - value that the frames y coord to be
 */
-(void)setUpMultiLineFrameBasedOnWidth:(CGFloat)maxWidth withStartXPosition:(CGFloat)startX withStartYPosition:(CGFloat)startY;

/*
 @method Adjusts UILabel's frame to begin at defined x position, to maxiumum width
 @param maxWidth - value that the frames width property will be
 @param startX - value that the frames x coord to be
 */
-(void)setUpMultiLineFrameBasedOnWidth:(CGFloat)maxWidth withStartXPosition:(CGFloat)startX;

/*
 @method Returns height value of UILabel based on content and max width
 @param width - max width of content
 @return height of UILabel
 */
-(CGFloat)getHeightBasedOnWidth:(CGFloat)width;

/*
 @method Returns size of UILabel based on content
 @return Size of UILabel
 */
-(CGSize)getSize;

@end

.m

@implementation UILabel(Size)

-(void)setUpMultiLineFrameWithStartXPosition:(CGFloat)startX withStartYPosition:(CGFloat)startY
{
	self.lineBreakMode = UILineBreakModeWordWrap;
	self.numberOfLines = 0;//instructs the label to contain any number of lines
	
	CGSize minSize = [self getSize];
	[self setFrame:CGRectMake(startX, startY, minSize.width, minSize.height)];
}

-(void)setUpMultiLineFrameBasedOnWidth:(CGFloat)maxWidth withStartXPosition:(CGFloat)startX withHeight:(CGFloat)maxHeight{
	self.lineBreakMode = UILineBreakModeWordWrap;
	self.numberOfLines = 0; //instructs the label to contain any number of lines
	
	CGFloat labelHeight = [self getHeightBasedOnWidth:maxWidth];
	CGFloat padding = ((maxHeight - labelHeight)/2); //center label within maxHeight box
	[self setFrame:CGRectMake(startX, padding, maxWidth, labelHeight)];
}

-(void)setUpMultiLineFrameBasedOnWidth:(CGFloat)maxWidth withStartXPosition:(CGFloat)startX withStartYPosition:(CGFloat)startY{
	
	self.lineBreakMode = UILineBreakModeWordWrap;
	self.numberOfLines = 0;//instructs the label to contain any number of lines
	
	CGFloat labelHeight = [self getHeightBasedOnWidth:maxWidth];
	[self setFrame:CGRectMake(startX, startY, maxWidth, labelHeight)];
}

-(void)setUpMultiLineFrameBasedOnWidth:(CGFloat)maxWidth withStartXPosition:(CGFloat)startX{
	self.lineBreakMode = UILineBreakModeWordWrap;
	self.numberOfLines = 0;//instructs the label to contain any number of lines
	
	CGFloat labelHeight = [self getHeightBasedOnWidth:maxWidth];
	[self setFrame:CGRectMake(startX, 0, maxWidth, labelHeight)];
}

-(CGFloat)getHeightBasedOnWidth:(CGFloat)maxWidth{
	
	CGSize size = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(maxWidth, 9999) lineBreakMode:self.lineBreakMode];
	
	return size.height;
}

-(CGSize)getSize{
	CGSize size = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(9999, 9999) lineBreakMode:self.lineBreakMode];
	
	return size;
}

@end

What do you think? Let me know by getting in touch on Twitter - @wibosco