Skip navigation

Vertical Text Alignment for UILabel?

85403 Views 30 Replies Latest reply: Jul 29, 2012 8:28 PM by Alex Zavatone RSS
1 2 3 Previous Next
DonnieM51 Level 1 Level 1 (15 points)
Currently Being Moderated
Oct 20, 2008 12:55 PM
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)
  • SexyAndOhSoWitty Level 3 Level 3 (575 points)
    Currently Being Moderated
    Oct 20, 2008 1:10 PM (in response to DonnieM51)
    What are your frame, bounds, center, and origin properties telling you about the size and placement of your label?

    Also, do you leave it set as numberOfLines = 2, or change it? I wonder if this makes a difference.
    MacBook Old, Mac OS X (10.5.5), iPhone 3G 16GB
  • orangekay Level 5 Level 5 (4,085 points)
    Currently Being Moderated
    Oct 20, 2008 1:30 PM (in response to DonnieM51)
    Looks like you get three options for UIBaselineAdjustment. If you want to do anything fancier then yes, I suspect you're going to have to do a lot of work. Text rendering is pretty complicated business on any platform.
    Several, Mac OS X (10.5.2)
  • just.do.it Level 3 Level 3 (840 points)
    Currently Being Moderated
    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
    MacBook Pro, Mac OS X (10.5.5)
  • ivan.m Level 1 Level 1 (0 points)
    Currently Being Moderated
    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.
    MacBook A1181, Mac OS X (10.5.5)
  • PatFerraz Level 1 Level 1 (0 points)
    Currently Being Moderated
    Mar 26, 2009 8:00 AM (in response to DonnieM51)
    Hi, I solve my problem using UITextView.
    MacBook, Mac OS X (10.5.6)
  • tadwook Level 1 Level 1 (0 points)
    Currently Being Moderated
    Apr 6, 2009 10:55 AM (in response to ivan.m)
    Thanks Ivan, your subclass works nicely for me.
  • Brad Eaton Level 1 Level 1 (0 points)
    Currently Being Moderated
    Apr 13, 2009 10:23 PM (in response to ivan.m)
    Excellent Job ivan.m! This subclass works great!
    MacBook Pro 17", Mac OS X (10.5.6), 2.66 GHz Intel Core 2 Duo / 4GB
  • Finger Tappin Level 1 Level 1 (0 points)
    Currently Being Moderated
    Jun 12, 2009 3:50 PM (in response to ivan.m)
    Ivan,

    I would like to thank you for sharing this code. Probably the single most helpful and useful thing I've found during my ramp up to understanding Objective C and iPhone Development. It works, it makes sense, and its shared in a complete functioning way that makes it a breeze (and a godsend) to find and use.

    Thanks for this Ivan.

    Jeff
    iMac, Mac OS X (10.5.7)
  • jeff_gobel Level 1 Level 1 (0 points)
    Currently Being Moderated
    Aug 2, 2009 7:12 AM (in response to ivan.m)
    Ivan, thanks for this class; really helped me.

    I made one small change in textRectForBounds...

    Instead of "rect.size.width", I use "bounds.size.width"

    This allows for UITextAlignmentCenter to still work for the label (otherwise it is always left justified).

    Thanks much,

    -Jeff
  • brucepdx Level 1 Level 1 (10 points)
    Currently Being Moderated
    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
  • HarrisIphone Level 1 Level 1 (0 points)
    Currently Being Moderated
    Sep 23, 2009 12:00 AM (in response to DonnieM51)
    .
    iPhone, iPhone OS 3.0.1
1 2 3 Previous Next

Actions

More Like This

  • Retrieving data ...

Bookmarked By (1)

Legend

  • This solved my question - 10 points
  • This helped me - 5 points
This site contains user submitted content, comments and opinions and is for informational purposes only. Apple disclaims any and all liability for the acts, omissions and conduct of any third parties in connection with or related to your use of the site. All postings and use of the content on this site are subject to the Apple Support Communities Terms of Use.