Выровнять текст по вертикали внутри UILabel
У меня есть UILabel
с местом для двух строк текста. Иногда, когда текст слишком короткий, этот текст отображается в вертикальном центре метки.
Как мне выровнять текст по вертикали, чтобы всегда быть в верхней части UILabel
?
51 ответ
Там нет никакого способа, чтобы установить вертикальное выравнивание на UILabel
, но вы можете получить тот же эффект, изменив рамку метки. Я сделал свои ярлыки оранжевыми, чтобы вы могли ясно видеть, что происходит.
Вот быстрый и простой способ сделать это:
[myLabel sizeToFit];
Если у вас есть метка с более длинным текстом, который будет занимать более одной строки, установите numberOfLines
в 0
(ноль здесь означает неограниченное количество строк).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Более длинная версия
Я сделаю свою метку в коде, чтобы вы могли видеть, что происходит. Вы можете настроить большую часть этого в Интерфейсном Разработчике также. Моя установка - приложение на основе просмотра с фоновым изображением, которое я сделал в 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
, как и два других режима усечения (голова и середина). NSLineBreakByClipping
также игнорируется. NSLineBreakByCharWrapping
работает как обычно. Ширина рамки все еще сужена, чтобы соответствовать самой правой букве.
Mark Amery комментариях Mark Amery дал исправление для NIB и раскадровок с использованием Auto Layout:
Если ваш ярлык включен в перо или раскадровку в качестве подпредставления
view
ViewController, который использует autolayout, а затем положить вашsizeToFit
позвонить вviewDidLoad
не будет работать, потому что размеры autoolayout и позиции подпредставлений после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;
Установите новый текст:
myLabel.text = @"Some Text"
Установить
maximum number
строк до 0 (автоматически):myLabel.numberOfLines = 0
Установите рамку этикетки на максимальный размер:
myLabel.frame = CGRectMake(20,20,200,800)
Вызов
sizeToFit
чтобы уменьшить размер фрейма, чтобы содержимое просто подходило:[myLabel sizeToFit]
Рамка для надписей теперь достаточно высокая и достаточно широкая, чтобы вместить ваш текст. Верхний левый должен быть неизменным. Я проверил это только с выравниванием по левому верхнему краю текста. Для других выравниваний вам, возможно, придется изменить кадр позже.
Кроме того, на моем ярлыке включена перенос слов.
На случай, если это кому-нибудь поможет, у меня возникла та же проблема, но я смог решить проблему, просто переключившись с использования. UILabel
использовать UITextView
, Я ценю это не для всех, потому что функциональность немного отличается.
Если вы переключитесь на использование UITextView
, вы можете отключить все свойства прокрутки, а также включить взаимодействие с пользователем... Это заставит его работать больше как метка.
Ссылаясь на расширение решения:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
должен быть заменен
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
Требуется дополнительное место в каждой добавленной новой строке, потому что iPhone UILabels
'Конец возврата каретки, кажется, игнорируется:(
Аналогично, alignBottom также должен быть обновлен с помощью @" \n@%"
на месте "\n@%"
(для инициализации цикла необходимо заменить на "for(int i=0..." тоже).
У меня работает следующее расширение:
// -- 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
Тогда позвони [yourLabel alignTop];
или же [yourLabel alignBottom];
после каждого назначения текста yourLabel.
Нет суеты, нет суеты
@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
Без суеты, без Objective-c, без суеты, кроме 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)
}
}
Решение раскадровки: самый простой и легкий способ - вставить Label
в StackView
и настройка StackView Axis
в Horizontal
, Alignment
в Top
в Attribute Inspector
из раскадровки.
Как и в ответе выше, но это было не совсем правильно, или просто вставлять в код, поэтому я немного его исправил. Добавьте это расширение либо в собственный файл.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];
Еще более быстрый (и более грязный) способ сделать это - установить для режима прерывания строки UILabel значение "Клип" и добавить фиксированное количество новых строк.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Это решение не будет работать для всех - в частности, если вы все еще хотите показывать "..." в конце вашей строки, если оно превышает количество отображаемых строк, вам нужно использовать одну из более длинные фрагменты кода - но во многих случаях это даст вам то, что вам нужно.
Вместо UILabel
вы можете использовать UITextField
which has vertical alignment option:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Я долго боролся с этим и хотел поделиться своим решением.
Это даст вам UILabel
это автоматически сократит текст до 0,5 масштаба и по центру текста по вертикали. Эти опции также доступны в раскадровке /IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Создать новый класс
LabelTopAlign
.h файл
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
.m файл
#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
редактировать
Вот более простая реализация, которая делает то же самое:
#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
В Интерфейсном Разработчике
- Задавать
UILabel
to size of biggest possible Text - Задавать
Lines
to '0' in Attributes Inspector
В вашем коде
- Set the text of the label
- Вызов
sizeToFit
on your label
Фрагмент кода:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Использование textRect(forBounds:limitedToNumberOfLines:)
,
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Для адаптивного интерфейса пользователя (iOS8 или более поздняя версия) вертикальное выравнивание UILabel должно быть установлено из StoryBoard путем изменения свойств noOfLines
=0` и
Ограничения
Настройка UILabel LefMargin, RightMargin и ограничений верхнего поля.
+ Изменить
Content Compression Resistance Priority For Vertical
=1000` Так что Вертикально> Горизонтально.
Отредактировано:
noOfLines=0
и следующих ограничений достаточно для достижения желаемых результатов.
Создайте подкласс UILabel. Работает как шарм:
// 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
Как обсуждено здесь.
Я написал утилиту для достижения этой цели. Вы можете посмотреть:
// корректируем высоту многострочной метки, чтобы она выровнялась по вертикали с верхней + (void) alignLabelWithTop:(UILabel *)label { CGSize maxSize = CGSizeMake(label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // получаем фактическую высоту CGSize actualSize = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = actualSize.height; label.frame = rect; }
.Как пользоваться? (Если lblHello создан Интерфейсным Разработчиком, поэтому я пропускаю некоторые детали атрибутов UILabel)
lblHello.text = @ "Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!"; lblHello.numberOfLines = 5; [Использует alignLabelWithTop:lblHello];
Я также написал это в своем блоге в качестве статьи: http://fstoke.me/blog/?p=2819
Я потратил некоторое время, чтобы прочитать код, а также код на введенной странице, и обнаружил, что все они пытаются изменить размер кадра метки, чтобы по умолчанию вертикальное выравнивание по центру не появлялось.
Однако в некоторых случаях мы хотим, чтобы метка занимала все эти пробелы, даже если метка имеет так много текста (например, несколько строк с одинаковой высотой).
Здесь я использовал альтернативный способ ее решения, просто добавив новые строки до конца метки (пожалуйста, обратите внимание, что я на самом деле унаследовал UILabel
, но это не обязательно)
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 "];
}
Вы можете использовать https://github.com/mattt/TTTAttributedLabel, он поддерживает вертикальное выравнивание.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Я взял предложения здесь и создал представление, которое может обернуть UILabel, измерить его и задать количество строк, чтобы оно было выровнено по верху. Проще говоря UILabel в качестве подпредставления:
@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
Я обнаружил, что ответы на этот вопрос сейчас немного устарели, поэтому добавим их для поклонников автоматического макета.
Авто макет делает этот вопрос довольно тривиальным. Предполагая, что мы добавляем метку UIView *view
следующий код выполнит это:
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}]];
Высота метки будет рассчитана автоматически (используя ее intrinsicContentSize
), и метка будет располагаться по горизонтали, в верхней части view
,
Я использовал много методов выше, и просто хочу добавить быстрый и грязный подход, который я использовал:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Убедитесь, что количество новых строк в строке приведет к тому, что любой текст заполнит доступное вертикальное пространство, и задайте UILabel для усечения любого переполненного текста.
Потому что иногда достаточно хорошо, достаточно хорошо.
FXLabel (на github) делает это из коробки, установив label.contentMode
в UIViewContentModeTop
, Этот компонент сделан не мной, но это компонент, который я часто использую, имеет множество функций и, кажется, работает хорошо.
Я хотел иметь метку, которая могла бы иметь несколько строк, минимальный размер шрифта и центрироваться как по горизонтали, так и по вертикали в родительском представлении. Я добавил мой ярлык программно на мой взгляд:
- (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];
}
А потом, когда я хотел изменить текст моего ярлыка...
- (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];
}
Надеюсь, что это помогает кому-то!
Для тех, кто читает это, потому что текст внутри вашего ярлыка не центрирован по вертикали, имейте в виду, что некоторые типы шрифтов не разработаны одинаково. например, если вы создадите метку с размером zapfino 16, вы увидите, что текст не идеально отцентрирован по вертикали.
тем не менее, работа с helvetica будет центрировать ваш текст по вертикали.
Если вы используете autolayout, установите для вертикального contentHuggingPriority значение 1000 в коде или IB. В IB вам, возможно, придется удалить ограничение высоты, установив приоритет 1 и затем удалив его.
Подкласс UILabel и ограничить рисование прямоугольника, как это:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Я попробовал решение, включающее заполнение новой строки и столкнулся с неправильным поведением в некоторых случаях. По моему опыту, проще ограничить рисование прямоугольника, как указано выше, чем связываться с numberOfLines
,
PS Вы можете легко представить поддержку 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];
}
Swift 5
Здесь отображается текст, начиная с верхнего левого угла и сохраняя возможный скорректированный размер текста.
final class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
super.drawText(in: .init(
origin: .zero,
size: textRect(
forBounds: rect,
limitedToNumberOfLines: numberOfLines
).size
))
}
}
Это старое решение, используйте автоматическое расположение на iOS >= 6
Мое решение:
1 / Разделить линии самостоятельно (игнорируя настройки переноса меток)
2 / Нарисуйте линии самостоятельно (игнорируя выравнивание меток)
@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
Пока вы не выполняете сложную задачу, вы можете использовать UITextView
вместо UILabels
,
Отключить прокрутку.
Если вы хотите, чтобы текст отображался полностью только пользователем sizeToFit
а также sizeThatFits:
методы