Ik heb een UILabel
met ruimte voor twee regels tekst. Soms, wanneer de tekst te kort is, wordt deze tekst weergegeven in het verticale midden van het label.
Hoe kan ik de tekst verticaal uitlijnen zodat deze altijd bovenaan de UILabel
staat?
Er is geen manier om de verticaal-uitlijning op een UILabel
in te stellen, maar je kunt hetzelfde effect krijgen door het kader van het label te veranderen's. Ik'heb mijn labels oranje gemaakt zodat je duidelijk kunt zien wat'er gebeurt.
Hier's de snelle en gemakkelijke manier om dit te doen:
[myLabel sizeToFit];
Als je een etiket hebt met langere tekst die meer dan één regel zal maken, zet numberOfLines
dan op 0
(nul betekent hier een onbeperkt aantal regels).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Langer versie
Ik'maak mijn label in code, zodat je kunt zien wat'er gebeurt. Je kunt het meeste ook in Interface Builder instellen. Mijn opzet is een View-Based App met een achtergrondafbeelding die ik in Photoshop heb gemaakt om de marges (20 punten) aan te geven. Het label heeft een aantrekkelijke oranje kleur zodat je kunt zien wat's er met de afmetingen gebeurt.
- (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];
}
Sommige beperkingen van het gebruik van sizeToFit
komen in het spel met midden- of rechts uitgelijnde tekst. Hier's wat er gebeurt:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Het label is nog steeds op maat met een vaste linkerbovenhoek. Je kunt de oorspronkelijke breedte van het label opslaan in een variabele en die na sizeToFit
instellen, of het een vaste breedte geven om deze problemen tegen te gaan:
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;
Merk op dat sizeToFit
de minimum breedte van het initiële label zal respecteren. Als je begint met een etiket van 100 breed en sizeToFit
oproept, zal het je een (mogelijk erg lang) etiket teruggeven met 100 (of een beetje minder) breedte. U kunt beter uw etiket instellen op de minimale breedte die u wilt voordat u de grootte aanpast.
Corrigeer de uitlijning van het label door de breedte van het frame te wijzigen]5
Enkele andere dingen om op te merken:
Of lineBreakMode
wordt gerespecteerd hangt af van hoe het is ingesteld's. NSLineBreakByTruncatingTail
(de standaard) wordt genegeerd na sizeToFit
, net als de andere twee truncatie modi (hoofd en midden). NSLineBreakByClipping
wordt ook genegeerd. NSLineBreakByCharWrapping
werkt zoals gebruikelijk. De breedte van het frame wordt nog steeds versmald om te passen bij de meest rechtse letter.
Mark Amery gaf een oplossing voor NIBs en Storyboards die Auto Layout gebruiken in de commentaren:
Als je label is opgenomen in een nib of storyboard als een subview van de
view
van een ViewController die autolayout gebruikt, dan zal het plaatsen van jesizeToFit
aanroep inviewDidLoad
niet werken, omdat autolayout de subviews vergroot en positioneert nadatviewDidLoad
is aangeroepen en onmiddellijk de effecten van jesizeToFit
aanroep ongedaan zal maken. Echter, het aanroepen vansizeToFit
vanuitviewDidLayoutSubviews
werkt wel.
Dit gebruikt de NSString
methode sizeWithFont:constrainedToSize:lineBreakMode:
om de frame hoogte te berekenen die nodig is om een string te passen, en stelt dan de oorsprong en breedte in.
Verander de grootte van het kader voor het label met de tekst die je wilt invoegen. Op die manier kun je een willekeurig aantal regels invoegen.
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;
Zoals het antwoord hierboven, maar het was niet helemaal juist, of gemakkelijk om in code te slaan, dus heb ik het een beetje opgeschoond. Voeg deze extensie toe aan zijn eigen .h en .m bestand of plak het gewoon boven de implementatie die je van plan bent te gebruiken:
#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
En dan om te gebruiken, zet je tekst in het label, en roep dan de juiste methode aan om het uit te lijnen:
[myLabel alignTop];
of
[myLabel alignBottom];
Ik heb even de tijd genomen om de code te lezen, evenals de code in de geïntroduceerde pagina, en ontdekte dat ze allemaal proberen de framegrootte van het etiket te wijzigen, zodat de standaard verticale uitlijning in het midden niet zou verschijnen.
In sommige gevallen willen we echter dat het etiket al die ruimte inneemt, zelfs als het etiket zoveel tekst bevat (b.v. meerdere rijen met gelijke hoogte).
Hier heb ik een alternatieve manier gebruikt om het op te lossen, door simpelweg nieuwe regels aan het eind van het label te plaatsen (let op, ik heb eigenlijk de UILabel
geërfd, maar dat is niet nodig):
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 "];
}