Antworten:
Es gibt keine Möglichkeit, die vertikale Ausrichtung auf a einzustellen UILabel
, aber Sie können den gleichen Effekt erzielen, indem Sie den Rahmen des Etiketts ändern. Ich habe meine Etiketten orange gemacht, damit Sie klar sehen können, was passiert.
Hier ist der schnelle und einfache Weg, dies zu tun:
[myLabel sizeToFit];
Wenn Sie eine Beschriftung mit längerem Text haben, die mehr als eine Zeile enthält, setzen Sie diese numberOfLines
auf 0
(Null bedeutet hier eine unbegrenzte Anzahl von Zeilen).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Längere Version
Ich werde mein Etikett im Code erstellen, damit Sie sehen können, was los ist. Das meiste davon können Sie auch im Interface Builder einrichten. Mein Setup ist eine ansichtsbasierte App mit einem Hintergrundbild, das ich in Photoshop erstellt habe, um Ränder (20 Punkte) anzuzeigen. Das Etikett hat eine attraktive orange Farbe, sodass Sie sehen können, was mit den Abmessungen los ist.
- (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
treten bei mittig oder rechts ausgerichtetem Text auf. Folgendes passiert:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Das Etikett hat immer noch eine feste Größe mit einer festen oberen linken Ecke. Sie können die Breite des Originaletiketts in einer Variablen speichern und danach festlegen sizeToFit
oder eine feste Breite festlegen , um diesen Problemen entgegenzuwirken:
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;
Beachten Sie, dass sizeToFit
die Mindestbreite Ihres ursprünglichen Etiketts eingehalten wird. Wenn Sie mit einem Etikett mit einer Breite von 100 beginnen und es aufrufen sizeToFit
, erhalten Sie ein (möglicherweise sehr hohes) Etikett mit einer Breite von 100 (oder etwas weniger) zurück. Möglicherweise möchten Sie Ihre Beschriftung auf die gewünschte Mindestbreite einstellen, bevor Sie die Größe ändern.
Einige andere Dinge zu beachten:
Ob dies lineBreakMode
respektiert wird, hängt davon ab, wie es eingestellt ist. NSLineBreakByTruncatingTail
(Standardeinstellung) wird nachher ignoriert sizeToFit
, ebenso wie die beiden anderen Kürzungsmodi (Kopf und Mitte). NSLineBreakByClipping
wird ebenfalls ignoriert. NSLineBreakByCharWrapping
funktioniert wie gewohnt. Die Rahmenbreite wird immer noch so verkleinert, dass sie zum Buchstaben ganz rechts passt.
Mark Amery gab in den Kommentaren einen Fix für NIBs und Storyboards mit Auto Layout:
Wenn Ihr Etikett in einer Schreibfeder oder einem Storyboard als Unteransicht
view
eines ViewControllers enthalten ist, der Autolayout verwendet, funktioniert das Einfügen IhressizeToFit
AnrufsviewDidLoad
nicht, da Autolayout-Größen und -Positionen, nach denen die UnteransichtenviewDidLoad
aufgerufen werden, die Auswirkungen Ihrer sofort rückgängig machensizeToFit
Anruf. Allerdings fordertsizeToFit
von innenviewDidLayoutSubviews
Willen Arbeit.
Dies verwendet die NSString
Methode sizeWithFont:constrainedToSize:lineBreakMode:
, um die Rahmenhöhe zu berechnen, die zum Anpassen einer Zeichenfolge erforderlich ist, und legt dann den Ursprung und die Breite fest.
Ändern Sie die Größe des Rahmens für das Etikett anhand des Textes, den Sie einfügen möchten. Auf diese Weise können Sie eine beliebige Anzahl von Zeilen aufnehmen.
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;
adjustsFontSizeToFitWidth
verwenden Sie sizeToFit und setzen Sie den Rahmen des Etiketts auf 0, 0, theWidthYouWant, label.frame.size.height (dies ist die neue Größe, die durch sizeToFit bestimmt wird). DANN geltenadjustsFontSizeToFitWidth
Stellen Sie den neuen Text ein:
myLabel.text = @"Some Text"
Setzen Sie die maximum number
Zeilen auf 0 (automatisch):
myLabel.numberOfLines = 0
Stellen Sie den Rahmen des Etiketts auf die maximale Größe ein:
myLabel.frame = CGRectMake(20,20,200,800)
Rufen Sie sizeToFit
an, um die Rahmengröße zu reduzieren, damit der Inhalt genau passt:
[myLabel sizeToFit]
Der Beschriftungsrahmen ist jetzt gerade hoch und breit genug, um zu Ihrem Text zu passen. Oben links sollte unverändert bleiben. Ich habe dies nur mit dem oben links ausgerichteten Text getestet. Bei anderen Ausrichtungen müssen Sie möglicherweise den Rahmen anschließend ändern.
Außerdem ist auf meinem Etikett der Zeilenumbruch aktiviert.
Bezug auf die Erweiterungslösung:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
sollte ersetzt werden durch
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
In jeder hinzugefügten neuen Zeile wird zusätzlicher Speicherplatz benötigt, da UILabels
die nachlaufenden Wagenrückläufe des iPhone ignoriert zu werden scheinen :(
In ähnlicher Weise sollte auch alignBottom mit einem @" \n@%"
anstelle von aktualisiert werden "\n@%"
(für die Zyklusinitialisierung muss auch "for (int i = 0 ...") 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
Rufen Sie dann [yourLabel alignTop];
oder [yourLabel alignBottom];
nach jeder yourLabel-Textzuweisung auf.
VerticalAlign
zwischen Klammern hinzufügen @implementation UILabel
. Als Neuling in Objective-C bin ich noch nie auf diese Syntax gestoßen. Wie heißt das?
sizeWithFont:constrainedToSize:lineBreakMode:
und sizeWithFont: werden beide in iOS7 abgeschrieben. Außerdem funktioniert diese Kategorie nur bei Beschriftungen, wenn numberOfLines größer als 0 ist.
Nur für den Fall, dass es jemandem hilft, hatte ich das gleiche Problem, konnte das Problem jedoch einfach durch Umschalten von "Verwenden" UILabel
auf "Verwenden" lösen UITextView
. Ich schätze, dass dies nicht jedermanns Sache ist, da die Funktionalität etwas anders ist.
Wenn Sie zu "Verwenden" wechseln UITextView
, können Sie alle Eigenschaften der Bildlaufansicht sowie "Benutzerinteraktion aktiviert" deaktivieren. Dadurch wird die Verwendung eher wie eine Beschriftung erzwungen.
UITextView
habe ich sofort das gewünschte Ergebnis erzielt.
Kein Muss, keine Aufregung
@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 Muss, kein Objective-C, keine Aufregung, 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 schlüpfen, also habe ich es ein bisschen aufgeräumt. Fügen Sie diese Erweiterung entweder zu Ihrer eigenen .h- und .m-Datei hinzu oder fügen Sie sie direkt über der Implementierung ein, die Sie verwenden möchten:
#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
Fügen Sie dann zur Verwendung Ihren Text in das Etikett ein und rufen Sie die entsprechende Methode zum Ausrichten auf:
[myLabel alignTop];
oder
[myLabel alignBottom];
Eine noch schnellere (und schmutzigere) Möglichkeit, dies zu erreichen, besteht darin, den Zeilenumbruchmodus des UILabel auf "Clip" zu setzen und eine feste Anzahl von Zeilenumbrüchen hinzuzufügen.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Diese Lösung funktioniert nicht für alle Benutzer. Insbesondere wenn Sie am Ende Ihrer Zeichenfolge immer noch "..." anzeigen möchten, wenn die Anzahl der angezeigten Zeilen überschritten wird, müssen Sie eine der folgenden Zeilen verwenden die längeren Codebits - aber in vielen Fällen erhalten Sie das, was Sie brauchen.
UILineBreakModeWordWrap
stattdessen.
Einfachster Ansatz mit Storyboard:
Einbetten Etikett in StackView und legen Sie die folgenden zwei Attribute von StackView im Attributinspektor fest:
1- Axis
bisHorizontal
,
2- Alignment
bisTop
UILabel
in eine UIView
Unterklasse zu platzieren (einfach UIView
ist normalerweise genug) und das Etikett nach unten wachsen zu lassen. Vielen Dank!
UILabel
das StackView aufheben und seine Arbeit erledigen müssen. Vielen Dank!
Anstelle von können UILabel
Sie verwenden, UITextField
die vertikale Ausrichtungsoption hat:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Ich habe lange mit diesem Problem zu kämpfen und wollte meine Lösung teilen.
Dadurch erhalten Sie einen UILabel
Text, der den Text automatisch auf 0,5 Skalen verkleinert und den Text vertikal zentriert. Diese Optionen sind auch in Storyboard / IB verfügbar.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
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
Hier ist eine einfachere Implementierung, die dasselbe tut:
#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
sizeToFit
Lösungen das macht tatsächlich den UILabel
Put jeden Text oben, auch wenn Sie dynamisch einen kürzeren Text mit einem längeren oder umgekehrt ersetzen.
Im Interface Builder
UILabel
die Größe des größtmöglichen Textes einstellenLines
Attributinspektor auf '0' setzenIn deinem Code
sizeToFit
Ihr Etikett anCode-Auszug:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Für die adaptive Benutzeroberfläche (iOS8 oder höher) muss die vertikale Ausrichtung von UILabel in StoryBoard durch Ändern der Eigenschaften
noOfLines
= 0` und festgelegt werden
Einschränkungen
Anpassen der Einschränkungen für UILabel LefMargin, RightMargin und Top Margin.
Veränderung
Content Compression Resistance Priority For Vertical
= 1000` So dass Vertikal> Horizontal.
Bearbeitet:
noOfLines=0
und die folgenden Einschränkungen reichen aus, um die gewünschten Ergebnisse zu erzielen.
Erstellen Sie eine Unterklasse von UILabel. Klappt wunderbar:
// 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 hier besprochen .
Ich habe eine util-Funktion geschrieben, um diesen Zweck zu erreichen. Sie können einen Blick darauf werfen:
// Passen Sie die Höhe eines mehrzeiligen Etiketts an, damit es vertikal zur Oberseite ausgerichtet wird + (void) alignLabelWithTop: (UILabel *) label { CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // tatsächliche Höhe ermitteln CGSize actualSize = [label.text sizeWithFont: label.font beschränkterToSize: maxSize lineBreakMode: label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = actualSize.height; label.frame = rect; }}
.Wie benutzt man? (Wenn lblHello vom Interface Builder erstellt wird, überspringe ich einige Details zu UILabel-Attributen.)
lblHello.text = @ "Hallo Welt! Hallo Welt! Hallo Welt! Hallo Welt! Hallo Welt! Hallo Welt! Hallo Welt! Hallo Welt!"; lblHello.numberOfLines = 5; [Utils alignLabelWithTop: lblHello];
Ich habe es auch in meinem Blog als Artikel geschrieben: http://fstoke.me/blog/?p=2819
Ich habe eine Weile gebraucht, um den Code sowie den Code auf der eingeführten Seite zu lesen, und festgestellt, dass alle versuchen, die Rahmengröße des Etiketts so zu ändern, dass die standardmäßige vertikale Ausrichtung in der Mitte nicht angezeigt wird.
In einigen Fällen möchten wir jedoch, dass die Beschriftung alle diese Leerzeichen belegt, auch wenn die Beschriftung so viel Text enthält (z. B. mehrere Zeilen mit gleicher Höhe).
Hier habe ich eine alternative Methode verwendet, um das Problem zu lösen, indem ich einfach Zeilenumbrüche an das Ende des Etiketts aufgefüllt habe (bitte beachten Sie, dass ich das tatsächlich geerbt habe UILabel
, es aber nicht erforderlich ist):
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 "];
}
Ich habe die Vorschläge hier aufgenommen und eine Ansicht erstellt, die ein UILabel umschließen kann, die Größe ändert und die Anzahl der Zeilen so einstellt, dass es oben ausgerichtet ist. Fügen Sie einfach ein UILabel als Unteransicht ein:
@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 TTTAttributedLabel verwenden , es unterstützt die vertikale Ausrichtung.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Ich habe festgestellt, dass die Antworten auf diese Frage jetzt etwas veraltet sind. Fügen Sie sie daher für die Fans des automatischen Layouts hinzu.
Das automatische Layout macht dieses Problem ziemlich trivial. Angenommen, wir fügen das Etikett hinzu, UIView *view
wird der folgende Code dies erreichen:
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 intrinsicContentSize
des Etiketts wird automatisch berechnet (mithilfe des Etiketts) und das Etikett wird von Kante zu Kante horizontal oben auf dem Etikett positioniert view
.
Ich habe viele der oben genannten Methoden verwendet und möchte nur einen schnellen und schmutzigen Ansatz hinzufügen, den 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 der Zeilenumbrüche in der Zeichenfolge dazu führt, dass Text den verfügbaren vertikalen Raum ausfüllt, und stellen Sie das UILabel so ein, dass überfließender Text abgeschnitten wird.
Weil manchmal gut genug gut genug ist .
UITextView
dass sie aufgerufen dlopen
werden können, um die Texteingabe zu unterstützen. Dies kann zu erheblichen Verzögerungen im UI-Thread führen, sodass dieser Ansatz viel leistungsfähiger ist!
Ich wollte ein Etikett, das mehrzeilig sein kann, eine minimale Schriftgröße aufweist und in der übergeordneten Ansicht sowohl horizontal als auch vertikal zentriert ist. Ich habe mein Etikett programmgesteuert zu meiner Ansicht hinzugefügt:
- (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 ich den Text meines Etiketts ändern wollte ...
- (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];
}
Hoffe das hilft jemandem!
FXLabel (auf Github) erledigt dies sofort, indem es label.contentMode
auf setzt UIViewContentModeTop
. Diese Komponente wurde nicht von mir hergestellt, aber es ist eine Komponente, die ich häufig verwende, die über unzählige Funktionen verfügt und anscheinend gut funktioniert.
Wenn Sie dies lesen, weil der Text in Ihrem Etikett nicht vertikal zentriert ist, beachten Sie, dass einige Schriftarten nicht gleich gestaltet sind. Wenn Sie beispielsweise ein Etikett mit der Zapfino-Größe 16 erstellen, wird der Text nicht perfekt vertikal zentriert.
Wenn Sie jedoch mit helvetica arbeiten, wird Ihr Text vertikal zentriert.
Verwenden Sie textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Unterklasse UILabel und schränken Sie das Zeichnungsrechteck wie folgt ein:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Ich habe die Lösung mit Newline-Padding ausprobiert und bin in einigen Fällen auf ein falsches Verhalten gestoßen. Nach meiner Erfahrung ist es einfacher, die Zeichnung wie oben zu beschränken, als sich damit zu beschäftigen numberOfLines
.
PS Sie können sich vorstellen, UIViewContentMode auf folgende Weise zu unterstützen:
- (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];
}
Solange Sie keine komplexe Aufgabe ausführen, können Sie UITextView
stattdessen verwenden UILabels
.
Deaktivieren Sie den Bildlauf.
Wenn Sie möchten, dass der Text vollständig angezeigt wird, nur Benutzer sizeToFit
und sizeThatFits:
Methoden
In kurzer Zeit
let myLabel : UILabel!
Damit Ihr Text Ihres Etiketts auf den Bildschirm passt und sich oben befindet
myLabel.sizeToFit()
Damit Ihre Schriftart des Etiketts an die Breite des Bildschirms oder eine bestimmte Breite angepasst wird.
myLabel.adjustsFontSizeToFitWidth = YES
und etwas TextAlignment für Label:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
[myLabel sizeToFit]
. Vielen Dank!
Dies ist eine alte Lösung. Verwenden Sie das Autolayout unter iOS> = 6
Meine Lösung:
@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