NSUserDefault
NSUserDefault

Reputation: 1834

How to align UILabel text from bottom?

How the UILabel can be aligned from bottom. Let say, my label can hold three line of text.If the input text is single line, then this line should come bottom of the label.Please refer the below image for better understanding. The orange area is the full frame of label.Currently it has one line and it is aligned center. So what I want is, it should always aligned bottom regardless of how many lines.

enter image description here

Please suggest your ideas.

Thank you.

Upvotes: 49

Views: 53245

Answers (13)

Mihail Salari
Mihail Salari

Reputation: 1581

class VerticalAlignedLabel: UILabel {
  
  let bottomSpacing: CGFloat = 10.0
  
  override func drawText(in rect: CGRect) {
    var newRect = rect
    let height = sizeThatFits(rect.size).height
    
    newRect.origin.y = rect.origin.y + rect.size.height - height - bottomSpacing
    newRect.size.height = height
    
    super.drawText(in: newRect)
  }
}

Upvotes: 0

Swift 5 version of @Dustin code:

Subclass:

class VerticallyAlignedUILabel: UILabel {
    
    enum Alignment {
        case top
        case bottom
    }
    
    var alignment: Alignment = .top
    
    override func drawText(in rect: CGRect) {
        var rect = rect
        if alignment == .top {
            rect.size.height = sizeThatFits(rect.size).height
        } else if alignment == .bottom {
            let height = sizeThatFits(rect.size).height
            rect.origin.y += rect.size.height - height
            rect.size.height = height
        }
        super.drawText(in: rect)
    }
}

Usage:

let myLabel = VerticallyAlignedUILabel()
myLabel.text = "vertically aligned text"
myLabel.alignment = .bottom

Upvotes: 1

wizard_of_oz
wizard_of_oz

Reputation: 101

Put your UILabel in a vertical UIStackView with a dummy view as a spacer. Also, set the dummy view with a lower hugging and compression priority.

Top to Bottom:

  • Label
  • Dummy View

Bottom to Top:

  • Dummy View
  • Label

Screenshot

Upvotes: 1

Dunbar
Dunbar

Reputation: 451

Swift 4.2 version using the contentMode property to set top and bottom:

class VerticalAlignedLabel: UILabel {
    
    override func drawText(in rect: CGRect) {
        var newRect = rect
        switch contentMode {
        case .top:
            newRect.size.height = sizeThatFits(rect.size).height
        case .bottom:
            let height = sizeThatFits(rect.size).height
            newRect.origin.y += rect.size.height - height
            newRect.size.height = height
        default:
            ()
        }
        
        super.drawText(in: newRect)
    }
}

Then setup your label like that:

let label = VerticalAlignedLabel()
label.contentMode = .bottom

Upvotes: 30

Rus
Rus

Reputation: 1

  1. use autoLayout)
textLabel.numberOfLines = 0
textLabel.textAlignment = .center

textLabel.topAnchor.constraint(greaterThanOrEqualTo: sView.topAnchor).isActive = true
textLabel.leadingAnchor.constraint(equalTo: sView.leadingAnchor).isActive = true
textLabel.trailingAnchor.constraint(equalTo: sView.trailingAnchor).isActive = true
textLabel.bottomAnchor.constraint(equalTo: sView.bottomAnchor).isActive = true

Upvotes: -2

Phantom59
Phantom59

Reputation: 1119

I recently ran into this problem and was able to solve it by putting my label in a stackview by itself. I got the idea from this post which had the same question but with multiple labels. The same technique can be used with a single label.

The stackview would have axis = horizontal and alignment = bottom (which is what does the trick).

My label is now perfectly aligned towards the bottom which is what I needed.

Upvotes: 2

Shruthi Palchandar
Shruthi Palchandar

Reputation: 11

In IB as @Tobe said Bottom constraint to superview should work, Incase if you have multiple subview or horizontal stack view with one element to have bottom constraint then use Layout Margin to be Fixed with bottom less than other margins enter image description here

Upvotes: 0

Paras Joshi
Paras Joshi

Reputation: 20551

Here are two ways of doing that...

1. First set numberOfLines to 0 and then use sizeToFit property of UILabel so your UILabel display with its contentSize.

yourLabel.numberOfLines = 0;

[yourLabel sizeToFit];

See more information from this link: Vertically align text within a UILabel

2. Another option is to take UITextField instead of UILabel and set userInteractionEnabled to NO like below...

[yourTextField setUserInteractionEnabled:NO];

and then set the contentVerticalAlignment property to bottom like below...

[yourTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentBottom];

UPDATE

Also, with UITextField, we can't achieve multiple lines. So instead we can use UITextView and set its userInteractionEnabled to NO. Then, use the code below to make it bottom aligned.

CGFloat topCorrect = ([label bounds].size.height - [label contentSize].height);
topCorrect = (topCorrect <0.0 ? 0.0 : topCorrect);
label.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};

Upvotes: 24

Tobe
Tobe

Reputation: 518

i only set a bottom constraint to the super view in IB which works for me without using code and also number of Lines for a maximum constraint.

Upvotes: 3

ahmedalkaff
ahmedalkaff

Reputation: 313

You can subclass UILabel and overriding the method :

- (void)drawTextInRect:(CGRect)rect

call super drawTextInRect with the rect where you want to use.

Upvotes: -2

autremoi
autremoi

Reputation: 261

Another option: use one label for your background color, I call this one originalLabel, and another for the text, called textLabel in my example. Then calculate the height and Y coordinate for textLabel:

[textLabel sizeToFit];
int height = textLabel.frame.size.height;
int yCoord = originalLabel.frame.origin.y + 
          originalLabel.frame.size.height - height;
textLabel.frame = CGRectMake( originalLabel.frame.origin.x, yCoord,
          textLabel.frame.size.width, height);

Upvotes: 0

barrast
barrast

Reputation: 1801

I had the same issue. Here is how I made to align the text to the bottom of my UILabel:

- (void)alignLabel:(UILabel *)l withText:(NSString *)text verticalAlignOption:(int)vertAlign{
CGSize stringSize = [text sizeWithFont:l.font constrainedToSize:l.frame.size lineBreakMode:l.lineBreakMode];

switch (vertAlign) {
    case 0: // align = top
        l.frame = CGRectMake(l.frame.origin.x,
                                   l.frame.origin.y,
                                   l.frame.size.width,
                                   stringSize.height
                                   );
        break;
    case 1: // align = bottom
        l.frame = CGRectMake(l.frame.origin.x,
                                   (l.frame.origin.y + l.frame.size.height) - stringSize.height,
                                   l.frame.size.width,
                                   stringSize.height
                                   );
        break;
    case 2: // align = middle
        // default
        break;
}

l.text = text;
}

Ahd you simple call the method like this to align to the bottom:

[self alignLabel:self.mediaTitle withText:@"My text to align" verticalAlignOption:1];

Upvotes: 0

Dustin
Dustin

Reputation: 1030

Subclass UILabel

@interface Label : UILabel

@end

Then override drawTextInRect like so

@implementation Label

- (void)drawTextInRect:(CGRect)rect
{
    if(alignment == top) {

        rect.size.height = [self sizeThatFits:rect.size].height;
    }

    if(alignment == bottom) {

        CGFloat height = [self sizeThatFits:rect.size].height;

        rect.origin.y += rect.size.height - height;
        rect.size.height = height;
    }

    [super drawTextInRect:rect];
}

@end

Upvotes: 20

Related Questions