Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Vertical Text Alignment for UILabel?

For UILabel on the iPhone, there is a property for horizontal text alignment which is textAlignment. But when I have a label that can hold 2 lines (numberOfLines = 2), when the text in the label is only one line, that line centers itself in the entire frame (that can hold two lines), when there are two lines, they both fit fine.

What I'd like to happen is if there is one line in a label that holds two, for the line NOT to be in the middle of the frame but to be pushed to the top of the frame as if there were a second line. In other languages (HTML that I can think of offhand) there is such thing as a verticalTextAlignment with options like top, center, bottom.

So, what am I missing here to make just one line of a UILabel to go to the top of its frame and not center itself in the middle of the frame?

Thanks for any direction.

MacBook Pro, Mac OS X (10.4.10)

Posted on Oct 20, 2008 12:55 PM

Reply
32 replies

Oct 20, 2008 1:20 PM in response to SexyAndOhSoWitty

I guess I don't know what you are asking re: frame, bounds, etc. I set the frame to appear in a view exactly where I want it and the size I want it so the frame is big enough to hold two lines at a specified font size (non-adjusting). Since any wrapping of text from one line into two is dynamic, I never know whether the text in the label is going to be one or two lines.

I set numberOfLines = 2 once when the label is initialized.

Googling around, there have been all kinds of queries asking to do what I've described and no one seems to have solved it (without subclassing UILabel itself and doing all sorts of calculations). It sure seems like there ought to be an easier answer. And why put text vertically in the center in the first place?

Oct 20, 2008 2:32 PM in response to DonnieM51

Found an answer, not all that complicated. The major hint was from gummyAvenger in this thread: http://discussions.apple.com/thread.jspa?messageID=7173902

So, here's what I put together for my UILabel so that a single line of text in a multi-line label will be at the top and not in the middle whenever I put new text in the label. Not fancy, but it works for me!


- (void)setUILabelTextWithVerticalAlignTop:(NSString *)theText {
// labelSize is hard-wired but could use constants to populate the size
CGSize labelSize = CGSizeMake(250, 50);
CGSize theStringSize = [theText sizeWithFont:myUILabel.font constrainedToSize:labelSize lineBreakMode:myUILabel.lineBreakMode];
myUILabel.frame = CGRectMake(myUILabel.frame.origin.x, myUILabel.frame.origin.y, theStringSize.width, theStringSize.height);
myUILabel.text = theText;
}

Oct 20, 2008 10:00 PM in response to DonnieM51

Hi, what about adding a few pieces of code:

- (void)setUILabelTextWithVerticalAlignTop:(NSString *)theText {
// labelSize is hard-wired but could use constants to populate the size
// Put the labels intended postion and size in here
CGRect labelFrame = CGRectMake(10, 20 250, 50);
CGSize theStringSize = [theText sizeWithFont:myUILabel.font constrainedToSize:labelSize lineBreakMode:myUILabel.lineBreakMode];
myUILabel.frame = CGRectMake(labelFrame.origin.x,
labelFrame.origin.y + (labelFrame.size.height - theStringSize.height) / 2.0,
theStringSize.width,
theStringSize.height);
myUILabel.text = theText;
}

Not testet, but i hope the idea becomes clear

Oct 21, 2008 6:21 AM in response to DonnieM51

Of course everything is a matter of style, but for fun, here's a reusable method to set and vertically align text in any label (that was briefly tested but doesn't check for number of lines and stuff like that). Since the label's frame gets modified, you have to keep around the original (max)frame somewhere and the original frame should pretty much be the size of the expected text (if you make it a lot higher than it needs, it will throw off the look).


- (void)setUILabel:(UILabel *)myLabel withMaxFrame:(CGRect)maxFrame withText:(NSString *)theText usingVerticalAlign:(int)vertAlign {
CGSize stringSize = [theText sizeWithFont:myLabel.font constrainedToSize:maxFrame.size lineBreakMode:myLabel.lineBreakMode];
switch (vertAlign) {
case 0: // vertical align = top
myLabel.frame = CGRectMake(myLabel.frame.origin.x,
myLabel.frame.origin.y,
myLabel.frame.size.width,
stringSize.height
);
break;

case 1: // vertical align = middle
// don't do anything, lines will be placed in vertical middle by default
break;

case 2: // vertical align = bottom
myLabel.frame = CGRectMake(myLabel.frame.origin.x,
(myLabel.frame.origin.y + myLabel.frame.size.height) - stringSize.height,
myLabel.frame.size.width,
stringSize.height
);
break;
}

myLabel.text = theText;
}

Mar 19, 2009 4:38 AM in response to DonnieM51

Hi, I'm quite new to Apple development and eventually passing most of problem topics discussed before.
And now I would like to share my UILabel subclass which supports vertical text alignment:


// Label2.h
// (c) 2009 Ivan Misuno, www.cuberoom.biz
#import <UIKit/UIKit.h>
typedef enum
{
VerticalAlignmentTop = 0, // default
VerticalAlignmentMiddle,
VerticalAlignmentBottom,
} VerticalAlignment;
@interface Label2 : UILabel
{
@private
VerticalAlignment _verticalAlignment;
}
@property (nonatomic) VerticalAlignment verticalAlignment;
@end




// Label2.mm
// (c) 2009 Ivan Misuno, www.cuberoom.biz
#import "Label2.h"
@implementation Label2
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
_verticalAlignment = VerticalAlignmentTop;

return self;
}
-(void)dealloc
{
[super dealloc];
}
-(VerticalAlignment) verticalAlignment
{
return _verticalAlignment;
}
-(void) setVerticalAlignment:(VerticalAlignment)value
{
_verticalAlignment = value;
[self setNeedsDisplay];
}
// align text block according to vertical alignment settings
-(CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect rect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
CGRect result;
switch (_verticalAlignment)
{
case VerticalAlignmentTop:
result = CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height);
break;
case VerticalAlignmentMiddle:
result = CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height);
break;
case VerticalAlignmentBottom:
result = CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height);
break;
default:
result = bounds;
break;
}
return result;
}
-(void)drawTextInRect:(CGRect)rect
{
CGRect r = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:r];
}
@end


Hope this will help somebody.
Regards.

Sep 22, 2009 11:12 AM in response to ivan.m

Here's a slightly improved version:


//
// VerticallyAlignedLabel.h
//
#import <Foundation/Foundation.h>
typedef enum VerticalAlignment {
VerticalAlignmentTop,
VerticalAlignmentMiddle,
VerticalAlignmentBottom,
} VerticalAlignment;
@interface VerticallyAlignedLabel : UILabel {
@private
VerticalAlignment verticalAlignment_;
}
@property (nonatomic, assign) VerticalAlignment verticalAlignment;
@end



//
// VerticallyAlignedLabel.m
//
#import "VerticallyAlignedLabel.h"
@implementation VerticallyAlignedLabel
@synthesize verticalAlignment = verticalAlignment_;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.verticalAlignment = VerticalAlignmentMiddle;
}
return self;
}
- (void)setVerticalAlignment:(VerticalAlignment)verticalAlignment {
verticalAlignment_ = verticalAlignment;
[self setNeedsDisplay];
}
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
switch (self.verticalAlignment) {
case VerticalAlignmentTop:
textRect.origin.y = bounds.origin.y;
break;
case VerticalAlignmentBottom:
textRect.origin.y = bounds.origin.y + bounds.size.height - textRect.size.height;
break;
case VerticalAlignmentMiddle:
// Fall through.
default:
textRect.origin.y = bounds.origin.y + (bounds.size.height - textRect.size.height) / 2.0;
}
return textRect;
}
-(void)drawTextInRect:(CGRect)requestedRect {
CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:actualRect];
}
@end

Vertical Text Alignment for UILabel?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.