Am un UILabel cu spațiu pentru două linii de text. Uneori, atunci când textul este prea scurt, acest text este afișat în centru vertical de etichetă.
Cum pot alinia vertical text să fie întotdeauna în partea de sus a UILabel
?
Nu's nici o modalitate de a seta vertical-align pe o `UILabel, dar puteți obține același efect prin schimbarea etichetei's cadru. Am'am făcut etichete de portocale astfel încât să puteți vedea în mod clar ceea ce's-a întâmplat.
Aici's cea mai rapidă și ușoară modalitate de a face acest lucru:
[myLabel sizeToFit];
Dacă aveți o eticheta cu text mai lung, care va face mai mult de o linie, set numberOfLines
a 0
(zero aici înseamnă un număr nelimitat de linii).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Versiune Mai Lungă
Am'll face casa mea de discuri din cod, astfel încât să puteți vedea ceea ce's întâmplă. Puteți seta cel mai mult de acest lucru în Interface Builder prea. Setup meu este o imagine-App pe bază, cu o imagine de fundal-am făcut în Photoshop pentru a arăta marjele (20 de puncte). Eticheta este un atractiv de culoare portocalie astfel încât să puteți vedea ceea ce's-a întâmplat cu dimensiunile.
- (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];
}
Unele limitări de utilizare sizeToFit` intră în joc cu centru - dreapta sau de-a aliniat textul. Aici's ce se întâmplă:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Eticheta este încă de dimensiuni cu un fix colțul din stânga sus. Puteți salva eticheta originală's latime într-o variabilă și setați-o după sizeToFit
, sau da o lățime fixă pentru a contracara aceste probleme:
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;
Rețineți că sizeToFit
va respect inițială eticheta's lățime minimă. Dacă începeți cu o etichetă de 100 de largă și de apel `sizeToFit pe ea, aceasta vă va da înapoi un (eventual foarte înalt) eticheta cu 100 (sau un pic mai puțin) lățime. S-ar putea să doriți să setați eticheta lățimea minimă doriți înainte de redimensionare.
Alte lucruri de reținut:
Dacă lineBreakMode
este respectat depinde de cât de l's set. NSLineBreakByTruncatingTail
(implicit) este ignorat după sizeToFit, ca sunt alte două moduri de trunchiere (cap și de mijloc).
NSLineBreakByClippingeste, de asemenea, ignorat.
NSLineBreakByCharWrapping ` funcționează ca de obicei. Lățimea cadrului este mai redus pentru a se potrivi la dreapta scrisoare.
Mark Amery - a dat un remediu pentru Penițe și Scenarii folosind Layout Auto din comentarii:
în Cazul în care eticheta este inclus într-o peniță sau storyboard ca un subview de "vedere" de o ViewController care folosește autolayout, apoi pune
sizeToFit
apel înviewDidLoad va't de lucru, pentru că autolayout dimensiuni și poziții subviews după viewDidLoad
este numit și imediat va anula efectelesizeToFit
apel. Cu toate acestea, numindusizeToFit
din cadrulviewDidLayoutSubviews
va locul de muncă.
Aceasta folosește NSString "metodă" sizeWithFont:constrainedToSize:lineBreakMode:` pentru a calcula înălțimea cadrului necesar pentru a se potrivi un șir de caractere, apoi stabilește originea și lățime.
Redimensiona cadrul etichetei folosind textul pe care doriți să-l inserați. În acest fel vă poate găzdui un număr de linii.
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;
myLabel.text = @"Text"
myLabel.numberOfLines = 0
myLabel.cadru = CGRectMake(20,20,200,800)
sizeToFit
pentru a reduce dimensiunea cadrului, astfel încât conținutul se potrivesc doar:[myLabel sizeToFit]
Etichetele cadru este acum doar de înaltă și destul de largă pentru a se potrivi dvs. de text. Stânga sus ar trebui să fie neschimbat. Am testat acest lucru doar cu partea de sus stânga-text aliniat. Pentru alte aliniamente, s-ar putea avea pentru a modifica cadru după aceea.
De asemenea, eticheta mea are ambalaj cuvânt activat.
Referindu-se la extinderea soluție:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
ar trebui să fie înlocuit cu
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
Este nevoie de spațiu suplimentar în fiecare adăugat newline, pentru că iPhone UILabels
' la final transportul se întoarce pare să fi ignorat :(
În mod similar, alignBottom ar trebui să fie actualizat, de asemenea, cu un @" \n@%" în loc de"\n@%"
(pentru ciclu de inițializare trebuie să fie înlocuit cu "pentru(int i=0..." prea).
Următoarele lucrări de extindere pentru mine:
// -- 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
Apoi sun `[yourLabel alignTop]; " sau " [yourLabel alignBottom]; după fiecare yourLabel text misiune.
Doar în cazul în care's de nici un ajutor de la nimeni, am avut aceeasi problema dar a fost capabil să rezolve problema, pur și simplu prin trecerea de la utilizarea UILabel
cu ajutorul UITextView
. Apreciez acest lucru nu e't pentru toată lumea, pentru că funcționalitatea este un pic diferit.
Dacă nu trece la utilizarea UITextView
, puteți dezactiva toate Parcurgere a Vizualiza proprietățile precum și Interacțiunea cu Utilizatorul Activat... Acest lucru va forța să acționeze mai mult ca o etichetă.
Fără figuri,
@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
Fără surle și Objective-c, nu tam-tam, dar 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)
}
}
Ca raspunsul de mai sus, dar nu a fost't destul de bine, sau ușor de palmă în cod, așa că am curatat-o un pic. Adăugați această extensie, fie pentru a-l's propriu .h și .m fișierul sau doar lipi deasupra punerea în aplicare intenționați să-l folosească:
#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
Și apoi de a utiliza, pune textul în etichetă, și apoi apel metoda potrivită pentru a-l alinia:
[myLabel alignTop];
sau
[myLabel alignBottom];
O chiar mai repede (și mai murdare) mod de a realiza acest lucru este prin setarea UILabel's de linie modul pentru "Clip" și adăugând o sumă de linii noi.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Această soluție a câștigat't de lucru pentru toată lumea-în special, dacă totuși doriți pentru a afișa "..." la sfârșitul șir dacă se depășește numărul de linii pe care le're arată, ai'll nevoie pentru a utiliza unul dintre cele mai biți de cod ... dar pentru o mulțime de cazuri de acest'll obține ceea ce aveți nevoie.
În loc de UILabel
ai putea folosi UITextField`, care are opțiune de aliniere verticală:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Cea mai simplă abordare folosind Rezumat:
Încorpora Label in StackView și setați următoarele două atribute ale StackView în Atribut Inspector:
1 - " Axă " a "Orizontale",
2- Aliniere
la Top
Am'am luptat cu aceasta pentru o lungă perioadă de timp și am vrut să-mi împărtășesc soluție.
Acest lucru vă va oferi o UILabel`, care va autoshrink text până la 0.5 cântare și pe verticală centrul de text. Aceste opțiuni sunt de asemenea disponibile în Rezumat/IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
A crea o nouă clasă
LabelTopAlign
.h fișier
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
.m fișierul
#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
Aici's o punere în aplicare mai simplă care face acelasi lucru:
#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
În Interface Builder
În codul dvs.
Fragment De Cod:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Pentru UI de Adaptare(iOS8 sau după) , Alinierea Verticală a UILabel este de a fi setat de la StoryBoard prin Schimbarea proprietăților
noOfLines
=0` și
Constrângeri
Ajustarea UILabel LefMargin, RightMargin și marginea de Sus Constrângeri.
Schimba Conținutul Rezistenta la Compresiune Prioritate Pentru Vertical
=1000
, Astfel încât pe Verticală>Orizontală .
Editat
noOfLines=0
și următoarele constrângeri sunt suficiente pentru a obține rezultatele dorite.
Crea o subclasă de UILabel. Funcționează ca un farmec:
// 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
Cum s-a discutat aici.
Am scris un util funcția de a realiza acest scop. Puteți lua o privire:
// pentru a regla înălțimea de un multi-linie etichetă pentru a face alinierea verticală cu partea de sus + (void) alignLabelWithTop:(UILabel *)eticheta { CGSize maxSize = CGSizeMake(eticheta.cadru.dimensiune.lățime, 999); eticheta.adjustsFontSizeToFitWidth = NU;// ia înălțimea reală CGSize actualSize = [eticheta.text sizeWithFont:eticheta.font constrainedToSize:maxSize lineBreakMode:eticheta.lineBreakMode]; CGRect rect = eticheta.cadru; rect.dimensiune.înălțime = actualSize.înălțime; eticheta.cadru = rect; }
.Cum să utilizați? (Dacă lblHello este creat de Interface builder, deci sar peste unele UILabel atribute detaliu)
lblHello.text = @"Hello World! Salut Lume! Salut Lume! Salut Lume! Salut Lume! Salut Lume! Salut Lume! Salut Lume!"; lblHello.numberOfLines = 5; [Utils alignLabelWithTop:lblHello];
De asemenea, am scris pe blogul meu un articol: http://fstoke.me/blog/?p=2819
Am luat un timp pentru a citi codul, precum și codul introdus în pagină, și a constatat că toate au de a modifica dimensiunea cadrului de etichetă, astfel încât default centru de aliniere verticală nu ar apărea.
Cu toate acestea, în unele cazuri, vrem eticheta pentru a ocupa toate aceste spații, chiar dacă eticheta nu au atât de mult text (de exemplu, în mai multe rânduri cu înălțime egală).
Aici, am folosit o modalitate alternativă de a rezolva, prin pur și simplu pad newline la sfârșitul eticheta (pls rețineți că de fapt am moștenit UILabel
, dar nu este necesar):
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 "];
}
Mi-am luat sugestii aici și a creat un punct de vedere care poate încheia o UILabel și va mărimea și setați numărul de linii, astfel încât acesta este top aliniate. Pur și simplu pune o UILabel ca un subview:
@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
Puteți utiliza TTTAttributedLabel, acesta susține alinierea verticală.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Am'am folosit o mulțime de metodele de mai sus, și vreau doar să adăugați o-rapid și-murdar abordare I'am folosit:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Asigurați-vă că numărul de linii noi în șir va provoca orice text pentru a umple spațiul vertical disponibil, și a stabilit UILabel pentru a trunchia orice debordant text.
Pentru că, uneori, destul de bun este destul de bun.
Am'am găsit răspunsurile la această întrebare sunt acum un pic out-of-data, astfel adăugând asta pentru auto layout fanii de acolo.
Auto layout face această problemă destul de banal. Presupunând că ne-am're adăugarea eticheta UIView *view
, urmatorul cod va realiza acest lucru:
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}]];
Eticheta's înălțime va fi calculat automat (folosind-o's intrinsicContentSize
) iar eticheta va fi poziționat edge-to-edge orizontal, în partea de sus a de "vedere".