
Not too long ago I needed to build a table of contents using a table view controller. It displayed a page title and a description. Our designer asked if I could change the leading in the line spacing for each. My initial response was no that can’t be done using a UILabel because the leading is automatic based on the size and font. I started to look for solutions and the only one I could come up with was to calculate the number of characters then break the title out into multiple UILabels. After more thought it would be more difficult to detect where to break it since it would have to break after a word, not just in the middle of a word, so I continued to search for a solution. Then I found MTLabel.
Change the Leading of your Label
MTLabel is a great framework built by Michal Tuszynski. It allows you to customize line spacing, specify if you want the label to resize itself based on text height and supports almost all features of UILabel. It actually is a UIView that you sub-class with type MTLabel. This was very useful and now I’m using it all the time when I need to make wrapping text look good with the right amount of line spacing.First, you’ll need to integrate the framework into your project.
1. Download the source code from the MTLabel GitHub.
2. Add the following files into your project:
– MTLabel.h
– MTLabel.m
3. Add the “CoreText.framework” framework to your project. To do this, access your target settings, click on “Summary”, scroll down to the “Linked Frameworks and Libraries” group and click the + button to add a new framework to your project. Search for “CoreText.framework”.
4. Include the following header at the top of your class:
#import "MTLabel.h"
4. Start coding!
MTLabel *titleLabelView = [MTLabel labelWithFrame:CGRectMake(15, 4, 252, 100) andText:@"This is where you place the text you need to wrap"]; [titleLabelView setFontColor:[UIColor blackColor]]; [titleLabelView setFont:[UIFont fontWithName:@"Helvetica-Bold" size:19.0]]; [titleLabelView setLineHeight:18]; [self.view addSubview:titleLabelView];
The code above shows a basic implementation of MTLabel. Define the frame of your label and the text, then style the font color and finally set the line height to the space you would like between the lines. Look at that, a lot nicer than UILabel.
Resizing MTLabels and Table View Cells
The example above works well if you know how much text you have and the exact space you have to place the label, but what if you need dynamic text like my table of contents example. Implementing this in a table view controller is a little tougher because each title and description can be different. The method below will calculate the height of the text view needed based on the font and width provided.-(CGSize) calcLabelSize:(NSString *)string withFont:(UIFont *)font maxSize:(CGSize)maxSize{ return [string sizeWithFont:font constrainedToSize:maxSize]; }
Let’s see this method in action below. We’ll calculate the expected height that we need the MTLabel to be based on what is returned from the method above.
CGSize titlemax = CGSizeMake(250, 100); CGSize titleexpected = [self calcLabelSize:[toc name] withFont:[UIFont fontWithName:@"Helvetica-Bold" size:19.0] maxSize:titlemax]; MTLabel *titleLabelView = [MTLabel labelWithFrame:CGRectMake(15, 4, 252, titleexpected.height) andText:[toc name]]; [titleLabelView setFontColor:[UIColor blackColor]]; [titleLabelView setFont:[UIFont fontWithName:@"Helvetica-Bold" size:19.0]]; [titleLabelView setLineHeight:18]; [cell addSubview:titleLabelView];
Notice that the height of the MTLabel is being set by “titleexpected.height” which was calculated using the “calcLabelSize” method. If you are using a table view controller you’ll also need to calculate and resize the cell height based on the font as well.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *key = [[_sections objectAtIndex:[indexPath section]] sectionName]; NSArray *items = [_titles objectForKey:key]; ClassName *toc = [items objectAtIndex:[indexPath row]]; CGSize max = CGSizeMake(250, 100); CGSize expected = [self calcLabelSize:[toc name] withFont:[UIFont fontWithName:@"Helvetica-Bold" size:19.0] maxSize:max]; return expected.height; }
I hope this short tutorial helped you dynamically set the height of a text label and make it look nice with the proper line spacing.