Frage

Ich habe einen UILabel mit Platz für zwei Textzeilen. Manchmal, wenn der Text zu kurz ist, wird dieser Text in der vertikalen Mitte des Etiketts angezeigt wird.

Wie vertikal ich den Text ausrichten immer an der Spitze der UILabel sein?

Bild repräsentiert eine UILabel mit vertikal zentrierte text

War es hilfreich?

Lösung

Es gibt keinen Weg, um die vertikale align auf einem UILabel zu setzen, aber Sie können durch Ändern des Labels Rahmen den gleichen Effekt. Ich habe meine Etiketten Orange gemacht, damit Sie sehen deutlich, was passiert.

Hier ist die schnelle und einfache Möglichkeit, dies zu tun:

    [myLabel sizeToFit];

sizeToFit ein Etikett drücken


Wenn Sie ein Etikett mit mehr Text haben, die mehr als eine Zeile machen, setzt numberOfLines auf 0 (Null bedeutet hier eine unbegrenzte Anzahl von Linien).

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

Längerer Beschriftungstext mit sizeToFit


Längere Version

Ich werde mein Label in Code machen, so dass Sie sehen, was los ist. Sie können auch die meisten dieser im Interface Builder einrichten. Mein Setup ist eine Ansicht Basierend App mit einem Hintergrundbild I in Photoshop Margen zeigen (20 Punkte). Das Label ist eine attraktive orange Farbe, damit Sie sehen, was mit den Dimensionen vor sich geht.

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 20 point top and left margin. Sized to leave 20 pt at right.
    CGRect labelFrame = CGRectMake(20, 20, 280, 150);
    UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
    [myLabel setBackgroundColor:[UIColor orangeColor]];

    NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
    [myLabel setText:labelText];

    // Tell the label to use an unlimited number of lines
    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    [self.view addSubview:myLabel];
}

Einige Einschränkungen bei der Verwendung sizeToFit ins Spiel zu kommen, mit Zentrum oder rechtsbündig Text. Hier ist, was passiert:

    // myLabel.textAlignment = NSTextAlignmentRight;
    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

eingeben Bild Beschreibung hier

Das Etikett ist so bemessen, noch mit einer festen oberen linken Ecke. Sie können das Originaletikett Breite in einer Variablen speichern und nach sizeToFit gesetzt, oder geben ihm eine feste Breite, diese Probleme zu begegnen:

    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    CGRect myFrame = myLabel.frame;
    // Resize the frame's width to 280 (320 - margins)
    // width could also be myOriginalLabelFrame.size.width
    myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
    myLabel.frame = myFrame;

label Ausrichtung


, dass sizeToFit Hinweis Ihre Anfangsetikett Mindestbreite respektieren. Wenn Sie mit einem Etikett 100 breit und rufen sizeToFit auf es starten, wird es Ihnen wieder ein (ggf. sehr hoch) Etikett mit 100 (oder etwas weniger) Breite. Sie könnten Ihr Etikett auf die minimale Breite einstellen möchten Sie vor Ändern der Größe wollen.

richtiges Etikett Ausrichtung durch die Rahmenbreite Skalieren

Einige andere Dinge zu beachten:

Ob lineBreakMode respektiert wird, hängt davon ab, wie es eingestellt ist. NSLineBreakByTruncatingTail (Standardeinstellung) wird nach sizeToFit ignoriert, da die beiden anderen Verkürzungs Modi (Kopf und Mitte) sind. NSLineBreakByClipping wird ebenfalls ignoriert. NSLineBreakByCharWrapping funktioniert wie gewohnt. Die Rahmenbreite ist noch verengt am weitesten rechts stehenden Buchstaben zu passen.


Mark Amery für NIBs ein Update gab und Storyboards mit Auto-Layout in den Kommentaren:

  

Wenn Ihr Etikett in einer Feder oder Storyboard als Subview des view eines Viewcontroller enthält, die automatische Layout verwendet, dann sizeToFit Anruf in viewDidLoad setzen wird nicht funktionieren, weil Autolayout Größen und positioniert die Subviews nach viewDidLoad genannt wird und wird sofort die Auswirkungen Ihrer sizeToFit Aufruf rückgängig machen. Allerdings ruft sizeToFit aus viewDidLayoutSubviews wird Arbeit.


My Original Antwort (für die Nachwelt / Referenz):

Dieses Verfahren verwendet die NSString sizeWithFont:constrainedToSize:lineBreakMode: die Rahmenhöhe zu berechnen, benötigt, um eine Zeichenkette zu passen, setzt dann den Ursprung und Breite.

Ändern Sie die Größe des Rahmens für das Label mit dem Text, den Sie einfügen möchten. So können Sie eine beliebige Anzahl von Zeilen aufnehmen kann.

CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont 
        constrainedToSize:maximumSize 
        lineBreakMode:self.dateLabel.lineBreakMode];

CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);

self.dateLabel.frame = dateFrame;

Andere Tipps

  1. Stellen Sie den neuen Text:

    myLabel.text = @"Some Text"
    
  2. Stellen Sie die maximum number von Linien auf 0 (automatisch):

    myLabel.numberOfLines = 0
    
  3. Stellen Sie den Rahmen des Etiketts auf die maximale Größe:

    myLabel.frame = CGRectMake(20,20,200,800)
    
  4. Anruf sizeToFit die Rahmengröße zu reduzieren, so dass die Inhalte nur passen:

    [myLabel sizeToFit]
    

Die Etiketten Rahmen ist jetzt nur noch hoch und breit genug, um Ihren Text zu passen. Die oben links sollte unverändert sein. Ich habe dies nur mit oben links ausgerichtetem Text getestet. Für andere Ausrichtungen, können Sie den Rahmen später ändern müssen.

Auch hat mein Label Zeilenumbruch aktiviert ist.

verweis auf die Erweiterungslösung:

for(int i=1; i< newLinesToPad; i++) 
    self.text = [self.text stringByAppendingString:@"\n"];

sollte

ersetzt werden
for(int i=0; i<newLinesToPad; i++)
    self.text = [self.text stringByAppendingString:@"\n "];

Zusätzlicher Raum wird in jedem hinzugefügt Newline benötigt, da iPhone UILabels‘Hinterzeilenumbrüche scheinen ignoriert zu werden: (

Ebenso sollte alignBottom auch mit einem @" \n@%" anstelle von "\n@%" aktualisiert werden (für den Zyklus der Initialisierung muss von "for (int i = 0 ..." too) ersetzt werden.

Die folgende Erweiterung funktioniert für mich:

// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

// -- file: UILabel+VerticalAlign.m
@implementation UILabel (VerticalAlign)
- (void)alignTop {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [self.text stringByAppendingString:@"\n "];
}

- (void)alignBottom {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
@end

Dann rufen Sie [yourLabel alignTop]; oder [yourLabel alignBottom]; nach jeder yourLabel Text-Zuordnung.

Für den Fall, es ist eine Hilfe für jeden, ich hatte das gleiche Problem, aber war in der Lage, das Problem einfach aus der Verwendung UILabel durch den Wechsel zu verwenden UITextView zu lösen. Ich schätze dies nicht jedermanns Sache ist, weil die Funktionalität ein bisschen anders ist.

Wenn Sie zur Verwendung UITextView wechseln, können Sie all Scroll-Ansicht Eigenschaften sowie Benutzerinteraktion aktiviert ausschalten ... Diese zwingen wird eher wie ein Etikett zu handeln.

eingeben Bildbeschreibung hier

Kein Durcheinander, kein Getue

@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

Kein Durcheinander, keine Objective-c, kein Stress, aber Swift 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

Swift 4.2

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

Wie die Antwort oben, aber es war nicht ganz richtig, oder einfach in Code zu schlagen, so reinigte ich es ein wenig. Fügen Sie diese Erweiterung entweder auf seine eigene .h und .m-Datei oder fügen Sie direkt über der Implementierung Sie beabsichtigen, es zu benutzen:

#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end


@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i<= newLinesToPad; i++)
    {
        self.text = [self.text stringByAppendingString:@" \n"];
    }
}

- (void)alignBottom
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i< newLinesToPad; i++)
    {
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
    }
}
@end

Und dann zu verwenden, setzen Sie Ihren Text in das Etikett, und dann die entsprechende Methode nennt es auszurichten:

[myLabel alignTop];

oder

[myLabel alignBottom];

Ein noch schneller (und dreckige) Weg dies zu tun ist durch den Zeilenumbruch-Modus des UILabel auf „Clip“ und das Hinzufügen eine festgelegte Menge von Zeilenumbrüchen.

myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];

Diese Lösung wird nicht für alle - insbesondere, wenn Sie noch zeigen wollen „...“ am Ende der Zeichenfolge, wenn es um die Anzahl der Linien überschreitet Sie zeigt, müssen Sie verwenden Sie eine der längeren Bit-Code -. aber für viele Fälle dies werde bekommen, was Sie brauchen

Statt UILabel können Sie UITextField verwenden, die vertikale Ausrichtung Option hat:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

Ich habe mit diesem für eine lange Zeit zu kämpfen und ich wollte meine Lösung teilen.

Dies gibt Ihnen einen UILabel, die Text auf 0,5 Skalen und vertikal zentriert den Text die automatische Verkleinerung wird. Diese Optionen sind auch in der Storyboard / IB zur Verfügung.

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

Storyboard-Lösung: Die einfachste und einfachste Weg ist Label in StackView einzubetten und StackView der Axis Einstellung Horizontal, Alignment in Top von Storyboard Attribute Inspector.

 image description hier

Erstellen Sie eine neue Klasse

LabelTopAlign

H-Datei

#import <UIKit/UIKit.h>


@interface KwLabelTopAlign : UILabel {

}

@end

.m-Datei

#import "KwLabelTopAlign.h"


@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect {
    int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
    if(rect.size.height >= lineHeight) {
        int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
        int yMax = textHeight;
        if (self.numberOfLines > 0) {
            yMax = MIN(lineHeight*self.numberOfLines, yMax);    
        }

        [super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
    }
}

@end

Bearbeiten

Hier ist eine einfachere Implementierung, macht das gleiche:

#import "KwLabelTopAlign.h"

@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect
{
    CGFloat height = [self.text sizeWithFont:self.font
                            constrainedToSize:rect.size
                                lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    rect.size.height = MIN(rect.size.height, height);
    [super drawTextInRect:rect];
}

@end

eingeben Bild Beschreibung hier

In Interface Builder

  • Stellen Sie UILabel der Größe der größten möglichen Text
  • Stellen Sie Lines auf '0' in Attribute Inspector

In Ihrem Code

  • Geben Sie den Text des Labels
  • Anruf sizeToFit auf dem Etikett

Code-Snippet:

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];

Für Adaptive UI (iOS8 oder nach), Vertikale Ausrichtung von UILabel ist von Storyboard festgelegt werden, indem die Eigenschaften ändern  noOfLines = 0 'und

  

Constraints

     
      
  1. Anpassen UILabel LefMargin, Right und Oberer Rand Constraints.

  2.   
  3. Ändern Content Compression Resistance Priority For Vertical = 1000` Damit Vertikal> Horizontal.

  4.   

 Einschränkungen von UILabel „ loading=

Editiert:

noOfLines=0

und die folgenden Einschränkungen sind genug, um die gewünschten Ergebnisse zu erzielen.

 image description hier

Erstellen Sie eine Unterklasse von UILabel. Funktioniert wie ein Zauber:

// TopLeftLabel.h

#import <Foundation/Foundation.h>

@interface TopLeftLabel : UILabel 
{
}

@end

// TopLeftLabel.m

#import "TopLeftLabel.h"

@implementation TopLeftLabel

- (id)initWithFrame:(CGRect)frame 
{
    return [super initWithFrame:frame];
}

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines 
{
    CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];    
    textRect.origin.y = bounds.origin.y;
    return textRect;
}

-(void)drawTextInRect:(CGRect)requestedRect 
{
    CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:actualRect];
}

@end

Wie bereits erwähnt hier .

Ich schrieb eine util Funktion dieses Ziel zu erreichen. Sie können einen Blick:

// adjust the height of a multi-line label to make it align vertical with top
+ (void) alignLabelWithTop:(UILabel *)label {
  CGSize maxSize = CGSizeMake(label.frame.size.width, 999);
  label.adjustsFontSizeToFitWidth = NO;

  // get actual height
  CGSize actualSize = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode];
  CGRect rect = label.frame;
  rect.size.height = actualSize.height;
  label.frame = rect;
}

.Wie zu benutzen? (Wenn lblHello von Interface Builder erstellt wird, so springe ich einige UILabel Detail Attribute)

lblHello.text = @"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!";
lblHello.numberOfLines = 5;
[Utils alignLabelWithTop:lblHello];

Ich schrieb es auch auf meinem Blog als Artikel: http://fstoke.me/blog/?p=2819

habe ich eine Weile, um den Code zu lesen, sowie den Code in der eingeführten Seite, und stellte fest, dass sie alle versuchen, die Rahmengröße von Etikett zu ändern, so dass die Standard-Center vertikale Ausrichtung nicht erscheinen.

Doch in einigen Fällen wollen wir das Etikett alle diese Räume zu besetzen, auch wenn das Etikett so viel Text hat (zum Beispiel mehrere Zeilen mit gleicher Höhe).

Hier habe ich eine alternative Art und Weise, sie zu lösen, indem man einfach Pad newlines bis zum Ende des Etiketts (pls merken, dass ich tatsächlich die UILabel geerbt, aber es ist nicht notwendig):

CGSize fontSize = [self.text sizeWithFont:self.font];

finalHeight = fontSize.height * self.numberOfLines;
finalWidth = size.width;    //expected width of label

CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];

int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

for(int i = 0; i < newLinesToPad; i++)
{
    self.text = [self.text stringByAppendingString:@"\n "];
}

nahm ich die Vorschläge hier und schuf eine Ansicht, die eine UILabel und Willen Größe wickeln können und die Anzahl der Zeilen so eingestellt, dass es oben ausgerichtet ist. Einfach eine UILabel als Subview setzen:

@interface TopAlignedLabelContainer : UIView
{
}

@end

@implementation TopAlignedLabelContainer

- (void)layoutSubviews
{
    CGRect bounds = self.bounds;

    for (UILabel *label in [self subviews])
    {
        if ([label isKindOfClass:[UILabel class]])
        {
            CGSize fontSize = [label.text sizeWithFont:label.font];

            CGSize textSize = [label.text sizeWithFont:label.font
                                     constrainedToSize:bounds.size
                                         lineBreakMode:label.lineBreakMode];

            label.numberOfLines = textSize.height / fontSize.height;

            label.frame = CGRectMake(0, 0, textSize.width,
                 fontSize.height * label.numberOfLines);
        }
    }
}

@end

Sie können mit TTTAttributedLabel unterstützt es die vertikale Ausrichtung.

@property (nonatomic) TTTAttributedLabel* label;
<...>

//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;

Ich habe über viele der Methoden verwendet, und will einfach nur einen schnellen und unsauberen Ansatz hinzuzufügen ich verwendet habe:

myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];

Stellen Sie sicher, dass die Anzahl von Zeilenumbrüchen in der Zeichenfolge einen beliebigen Text bewirkt, dass der verfügbaren vertikalen Raum zu füllen, und die UILabel setzen alle überquell Text gekürzt werden soll.

Weil manchmal gut genug ist gut genug .

Ich wollte ein Label haben, die mit mehreren Linien zu haben, war in der Lage, eine Mindestschriftgröße und zentrierte sowohl horizontal als auch vertikal in seinen übergeordneten Ansicht. Ich habe mein Label programmatisch meine Sicht:

- (void) customInit {
    // Setup label
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.label.numberOfLines = 0;
    self.label.lineBreakMode = UILineBreakModeWordWrap;
    self.label.textAlignment = UITextAlignmentCenter;

    // Add the label as a subview
    self.autoresizesSubviews = YES;
    [self addSubview:self.label];
}

Und dann, als wollte ich den Text meines Labels ändern ...

- (void) updateDisplay:(NSString *)text {
    if (![text isEqualToString:self.label.text]) {
        // Calculate the font size to use (save to label's font)
        CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
        self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
        CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) {
            self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
            textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        }
        // In cases where the frame is still too large (when we're exceeding minimum font size),
        // use the views size
        if (textSize.height > self.frame.size.height) {
            textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
        }

        // Draw 
        self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
        self.label.text = text;
    }
    [self setNeedsDisplay];
}

Hoffnung, dass jemand hilft!

Ich habe die Antworten auf diese Frage zu finden sind jetzt ein bisschen out-of-date, so dass das Hinzufügen dieser für die automatische Layout-Fans da draußen.

Auto-Layout macht dieses Problem ziemlich trivial. Unter der Annahme, wir das Etikett UIView *view sind hinzufügen, wird der folgende Code erreicht dies:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];

[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];

Die Höhe des Etiketts automatisch berechnet werden (unter Verwendung ihrer intrinsicContentSize) und das Etikett wird von Kante zu Kante horizontal positioniert werden, an der Spitze des view.

FXLabel (auf Github) tut dies aus der Box von label.contentMode Einstellung UIViewContentModeTop. Diese Komponente wird nicht von mir gemacht, aber es ist eine Komponente, die ich häufig verwenden und hat eine Unmenge an Features und scheint gut zu funktionieren.

Was ich in meiner app tat, war die UILabel Linie Eigenschaft auf 0 und setzt als eine untere Beschränkung des UILabel zu schaffen und sicherzustellen, dass es auf> = 0 gesetzt wird, wie unten in der Abbildung dargestellt. eingeben Bild Beschreibung hier

für alle, die dies lesen, weil der Text in Ihrem Label ist nicht vertikal zentriert, bedenken Sie, dass einige Schriftarten sind nicht gleichmäßig entwickelt. zum Beispiel, wenn Sie ein Etikett mit zapfino Größe 16 zu erstellen, werden Sie sehen, der Text nicht perfekt vertikal zentriert ist.

jedoch mit Helvetica arbeiten, werden vertikal Ihren Text zentrieren.

Unterklasse UILabel und beschränken die Zeichnung Rechteck, wie folgt aus:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];
    rect.size.height = MIN(rect.size.height, sizeThatFits.height);

    [super drawTextInRect:rect];
}

habe ich versucht, die Lösung Newline padding beteiligt und lief in einem falsches Verhalten in einigen Fällen. Nach meiner Erfahrung ist es einfacher, die Zeichnung rect wie oben als Chaos mit numberOfLines zu beschränken.

P. S. Sie können sich leicht vorstellen, auf diese Weise unterstützen UIViewContentMode:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];

    if (self.contentMode == UIViewContentModeTop) {
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }
    else if (self.contentMode == UIViewContentModeBottom) {
        rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }

    [super drawTextInRect:rect];
}

Wenn Sie automatisches Layout verwenden, stellen Sie die vertikale contentHuggingPriority bis 1000, entweder im Code oder IB. In IB können müssen Sie dann durch eine Höhenbeschränkung entfernen Einstellung ist es Priorität 1 und löschen Sie es dann.

Mit textRect(forBounds:limitedToNumberOfLines:).

class TopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        super.drawText(in: textRect)
    }
}

Solange Sie keine komplexe Aufgabe tun, Sie UITextView statt UILabels verwenden können.

Deaktivieren

die Schriftrolle.

Wenn Sie den Text vollständig nur Benutzer sizeToFit und sizeThatFits: Methoden angezeigt werden

In swift,

let myLabel : UILabel!

Um Ihren Text Ihrer Etiketten zu machen Bildschirm anzupassen und es ist auf der Oberseite

myLabel.sizeToFit()

Um die Schrift von Etiketten machen auf die Breite des Bildschirms oder bestimmte Breite Größe zu passen.

myLabel.adjustsFontSizeToFitWidth = YES

und einige Textalignment für Label:

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified

Dies ist eine alte Lösung, verwenden automatisches Layout auf iOS> = 6

Meine Lösung:
1 / Split Linien von mir (ohne Berücksichtigung von Etiketten Wrap-Einstellungen)
2 / Zeichnen von Linien von mir (ohne Berücksichtigung von Etiketten Ausrichtung)


@interface UITopAlignedLabel : UILabel

@end

@implementation UITopAlignedLabel

#pragma mark Instance methods

- (NSArray*)splitTextToLines:(NSUInteger)maxLines {
    float width = self.frame.size.width;

    NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSMutableArray* lines = [NSMutableArray array];

    NSMutableString* buffer = [NSMutableString string];    
    NSMutableString* currentLine = [NSMutableString string];

    for (NSString* word in words) {
        if ([buffer length] > 0) {
            [buffer appendString:@" "];
        }

        [buffer appendString:word];

        if (maxLines > 0 && [lines count] == maxLines - 1) {
            [currentLine setString:buffer];
            continue;
        }

        float bufferWidth = [buffer sizeWithFont:self.font].width;

        if (bufferWidth < width) {
            [currentLine setString:buffer];
        }
        else {
            [lines addObject:[NSString stringWithString:currentLine]];

            [buffer setString:word];
            [currentLine setString:buffer];
        }
    }

    if ([currentLine length] > 0) {
        [lines addObject:[NSString stringWithString:currentLine]];
    }

    return lines;
}

- (void)drawRect:(CGRect)rect {
    if ([self.text length] == 0) {
        return;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, self.textColor.CGColor);
    CGContextSetShadowWithColor(context, self.shadowOffset, 0.0f, self.shadowColor.CGColor);

    NSArray* lines = [self splitTextToLines:self.numberOfLines];
    NSUInteger numLines = [lines count];

    CGSize size = self.frame.size;
    CGPoint origin = CGPointMake(0.0f, 0.0f);

    for (NSUInteger i = 0; i < numLines; i++) {
        NSString* line = [lines objectAtIndex:i];

        if (i == numLines - 1) {
            [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeTailTruncation];            
        }
        else {
            [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeClip];
        }

        origin.y += self.font.lineHeight;

        if (origin.y >= size.height) {
            return;
        }
    }
}

@end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top