Monday, September 17, 2012

UILabel - Change Vertical Alignment

Lately I promised you more posts about my experience in iOS programming. Unexpectedly my company needs lots of iOS-apps so I had no time to share my new knowledge with you which I want to catch up right now starting with a problem I faced today.

The Xcode is a great environment to visually develop iOS apps, but like any other IDE it has some limitations. Today I tried to create a custom UITableViewCell containing some UILabels and UIImages. One of this labels should show two lines of text with truncated tail (with "..." as suffix).

Up to here no problem at all, as long as you are happy with the apple defined standard behaviour of multiline labels. In a usual label if the text does not cover both lines (perhaps it covers in portrait, but not in landscape) then the label shows just one line with centred vertical alignment. In most of the cases this could be an option, however it does not fit into the design for our app. U, like me probably think, that it should not be a problem to change the vertical alignment, however this behaviour is not easy to change.

I found some posts in which other developers suggest to use the sizeToFit method of the UILabel. Despite that, generally this would be a solution, in my case the label is contained into a UITableCellView which adds one more level of difficulty to the problem. In a UITable the Cells are not created for each data item, but reused several times and so it would reuse the resized label over and over again, and as I saw from several tests, even though I called sizeToFit after each assignment, the Label is not reset.

In other posts I found the hint, that I have to reset the frame to its initial size before calling sizeToFit, in order to have it working correctly. That's already the right way, but what's the size to set it to? The one defined in the storyboard? Close, but what if you have more than one storyboard?

The solution is to define the hight and width according to the autosized properties in the storyboard reduced by the number of remaining lines times the hight of a line. The latter needs to be calculated using the font and the font size.

    [cell.myLabel setText:[dataDictionary valueForKey:kMyLabel]];
    CGSize titleSize = [cell.
myLabel.text sizeWithFont:cell.myLabel.font constrainedToSize:CGSizeMake(cell.frame.size.width,40.0f) lineBreakMode:cell.myLabel.lineBreakMode];  
    //Adjust the label the the new height
    CGRect newFrame = cell.eventTitleLabel.frame;
    newFrame.size.height = titleSize.height;
    cell.myLabel.frame = newFrame;

The code is quite self explaining, except maybe the "40.0f". This value is just saying tht in my case the height of the Label should be limited to 2 lines in my case. This could be improved by dynamically calculate the size of one row times the lines you want to display.

That's more or less the same solution I came up with implemented in a Category, which makes it simple and reusable.

No comments: