Имам UILabel
с място за два реда текст. Понякога, когато текстът е твърде кратък, той се показва във вертикалния център на етикета.
Как да подравня вертикално текста, за да бъде винаги в горната част на UILabel
?
Няма начин да се зададе вертикално подравняване на UILabel
, но можете да постигнете същия ефект, като промените рамката на етикета. Направих моите етикети оранжеви, за да можете ясно да видите какво се случва.
Ето бързия и лесен начин да направите това:
[myLabel sizeToFit];
Ако имате етикет с по-дълъг текст, който ще се състои от повече от един ред, задайте numberOfLines
на 0
(нула тук означава неограничен брой редове).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Дълга версия
Ще направя етикета си в код, за да можете да видите какво'се случва. Можете да настроите повечето от това и в Interface Builder. Моята настройка е приложение, базирано на изглед, с фоново изображение, което направих във Photoshop, за да покажа полетата (20 точки). Етикетът е в атрактивен оранжев цвят, за да можете да видите какво'става с размерите.
- (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];
}
Някои ограничения при използването на sizeToFit
се проявяват при текст, подравнен в центъра или вдясно. Ето какво се случва:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Етикетът все още е оразмерен с фиксиран горен ляв ъгъл. Можете да запазите ширината на оригиналния етикет'в променлива и да я зададете след sizeToFit
, или да му зададете фиксирана ширина, за да се справите с тези проблеми:
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;
Обърнете внимание, че sizeToFit
ще се съобрази с минималната ширина на вашия първоначален етикет'. Ако започнете с етикет с ширина 100 и извикате sizeToFit
за него, той ще ви върне (вероятно много висок) етикет с ширина 100 (или малко по-малко). Може да искате да зададете минималната ширина на етикета, която искате, преди да промените размера.
Някои други неща за отбелязване:
Дали ще се спазва lineBreakMode
зависи от начина, по който е зададен. NSLineBreakByTruncatingTail
(по подразбиране) се игнорира след sizeToFit
, както и другите два режима на съкращаване (head и middle). NSLineBreakByClipping
също се игнорира. NSLineBreakByCharWrapping
работи както обикновено. Широчината на рамката все още се стеснява, за да се побере в най-дясната буква.
Mark Amery даде поправка за NIB и Storyboards, използващи Auto Layout, в коментарите:
Ако вашият етикет е включен в ниб или сториборд като под-изглед на
view
на ViewController, който използва autolayout, тогава поставянето на вашето извикване наsizeToFit
вviewDidLoad
няма да сработи, защото autolayout оразмерява и позиционира под-изгледите след извикването наviewDidLoad
и веднага ще отмени ефекта от вашето извикване наsizeToFit
. Обаче извикването наsizeToFit
от рамките наviewDidLayoutSubviews
ще работи.
Това използва метода NSString
sizeWithFont:constrainedToSize:lineBreakMode:
, за да изчисли височината на рамката, необходима за побиране на низ, след което задава началото и ширината.
Променете размера на рамката за етикета, като използвате текста, който искате да вмъкнете. По този начин можете да вместите произволен брой редове.
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;
Подобно на отговора по-горе, но той не беше съвсем правилен или лесен за въвеждане в кода, така че го изчистих малко. Добавете това разширение или към собствен .h и .m файл, или просто го поставете точно над имплементацията, която възнамерявате да използвате:
#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
И след това, за да го използвате, поставете вашия текст в етикета и след това извикайте съответния метод, за да го подравните:
[myLabel alignTop];
или
[myLabel alignBottom];
Отделих известно време, за да прочета кода, както и кода във въведената страница, и установих, че всички те се опитват да променят размера на рамката на етикета, така че вертикалното подравняване по подразбиране да не се появи в центъра.
В някои случаи обаче искаме етикетът да заеме всички тези пространства, дори ако етикетът наистина има толкова много текст (например няколко реда с еднаква височина).
Тук използвах алтернативен начин за решаване, като просто подредих нови редове в края на етикета (pls note that I actually inherited the UILabel
, but it is not necessary):
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 "];
}