У меня есть UILabel
с пространством для двух строк текста. Иногда, когда текст слишком короткий, этот текст отображается в вертикальном центре метки.
Как вертикально выровнять текст всегда в верхней части UILabel
?
У меня есть UILabel
с пространством для двух строк текста. Иногда, когда текст слишком короткий, этот текст отображается в вертикальном центре метки.
Как вертикально выровнять текст всегда в верхней части UILabel
?
Там нет никакого способа установить вертикальное выравнивание на 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
вступают в игру с center- или текстом, выровненным по правому краю. Вот что происходит:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Ярлык по-прежнему имеет фиксированный верхний левый angular. Вы можете сохранить исходную ширину метки в переменной и установить ее после sizeToFit
или задать фиксированную ширину, чтобы противостоять этим проблемам:
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
CGRect myFrame = myLabel.frame;
// Resize the frame 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
работает как обычно. Ширина рамки все еще сужена, чтобы соответствовать самой правой букве.
Марк Эмери дал исправление для 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]
Рамка для надписей теперь достаточно высокая и достаточно широкая, чтобы вместить ваш текст. Верхний левый должен быть неизменным. Я проверял это только с выравниванием по верхнему левому краю текста. Для других выравниваний вам, возможно, придется изменить кадр позже.
Кроме того, на моем ярлыке включена перенос слов.
Ссылаясь на решение для расширения:
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 также должен быть обновлен с помощью @" \[email protected]%"
вместо "\[email protected]%"
(для инициализации цикла необходимо заменить на "for (int я = 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.
На всякий случай, если бы это помогало кому-либо, у меня была такая же проблема, но я смог решить проблему, просто переключившись с UILabel
на UITextView
. Я понимаю, что это не для всех, потому что функциональность немного отличается.
Если вы переключитесь на использование UITextView
, вы можете отключить все свойства просмотра прокрутки, а также включенное взаимодействие с пользователем... Это заставит его действовать как ярлык.
Нет суеты, нет суеты
@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)
}
}
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)
}
}
Как и в предыдущем ответе, но это было не совсем правильно или легко похлопать по коду, поэтому я немного почистил его. Добавьте это расширение либо к своему собственному файлу .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 на "Clip" и добавив фиксированное количество строк новой строки.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Это решение не будет работать для всех - в частности, если вы все еще хотите показать "..." в конце строки, если она превышает количество строк, которые вы показываете, вам нужно будет используйте один из более длинных битов кода, но для многих случаев это даст вам то, что вам нужно.
Вместо UILabel
вы можете использовать UITextField
, у которого есть опция вертикального выравнивания:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Решение раскадровки: самым простым и простым способом является встраивание Label
в StackView
и установка Axis
StackView в Horizontal
, Alignment
до Top
в Attribute Inspector
из раскадровки.
Я долгое время боролся с этим, и я хотел поделиться своим решением.
Это даст вам UILabel
, который будет автоматически печатать текст до 0,5 шкалы и вертикально центрировать текст. Эти параметры также доступны в Storyboard/IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Создайте новый класс
LabelTopAlign
.h файл
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
.m file
#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
В интерфейсе Builder
UILabel
размер максимально возможного текстаLines
в '0' в Инспекторе атрибутовВ вашем коде
sizeToFit
на вашей этикеткеФрагмент кода:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Для Adaptive UI (iOS8 или после) вертикальное выравнивание UILabel должно быть установлено из StoryBoard путем изменения свойств
noOfLines
= 0` и
Ограничения
Корректировка ограничений UILabel LefMargin, RightMargin и Top Margin.
Измените
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
Как обсуждалось здесь.
Я написал функцию утилиты для достижения этой цели. Вы можете посмотреть:
// adjust the height of a multi-line label to make it align vertical with top + (void) alignLabelWithTop:(UILabel *)label { CGSize maxSize = CGSizeMake(label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // get actual height 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; [Utils 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 "];
}
Я воспользовался этими предложениями и создал представление, которое может обернуть 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
Вы можете использовать TTTAttributedLabel, он поддерживает вертикальное выравнивание.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view or viewController init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Я использовал много методов выше и просто хочу добавить быстрый и грязный подход, который я использовал:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Убедитесь, что количество строк в строке приведет к тому, что любой текст заполнит доступное вертикальное пространство и установите UILabel для обрезания любого переполняющего текста.
Потому что иногда достаточно хорошо.
Я нашел ответы на этот вопрос в настоящее время немного устаревшими, поэтому добавив это для поклонников автомакетов там.
Автоматическая компоновка делает эту проблему довольно тривиальной. Предполагая, что мы добавляем метку к 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
.
В моем приложении я установил для свойства линии UILabel значение 0, а также для создания нижнего ограничения UILabel и убедитесь, что для него установлено значение> = 0, как показано на рисунке ниже.
Я хотел иметь метку, которая могла бы иметь многострочные линии, минимальный размер шрифта и центрироваться как по горизонтали, так и по вертикали в своем родительском представлении. Я добавил программный код на мой взгляд:
- (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 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];
}
Надеюсь, что это поможет кому-то!
FXLabel (на github) делает это из коробки, устанавливая label.contentMode
на UIViewContentModeTop
. Этот компонент не сделан мной, но это компонент, который я часто использую и имеет множество функций, и, похоже, работает хорошо.
для всех, кто читает это, потому что текст внутри вашей метки не имеет вертикальной ориентации, помните, что некоторые типы шрифтов не разработаны одинаково. например, если вы создаете метку с размером zapfino 16, вы увидите, что текст не идеально по вертикали.
однако работа с helvetica будет вертикально центрировать ваш текст.
Подкласс UILabel и ограничить прямоугольник рисования, например:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Я попробовал решение с добавлением новой строки и в некоторых случаях столкнулся с некорректным поведением. По моему опыту, легче ограничивать рисование прямоугольником как выше, чем беспорядок с numberOfLines
.
P.S. Вы можете легко представить поддержку 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];
}
Если вы используете автозапуск, установите вертикальный контентHuggingPriority 1000, либо в коде, либо в IB. В IB вам может потребоваться удалить ограничение по высоте, установив приоритет на 1, а затем удалив его.
Используйте textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Пока вы не выполняете сложную задачу, вы можете использовать UITextView
вместо UILabels
.
Отключить прокрутку.
Если вы хотите, чтобы текст отображался полностью как пользовательские методы sizeToFit
и sizeThatFits:
В быстром,
let myLabel : UILabel!
Чтобы текст вашего ярлыка соответствовал экрану, а он сверху
myLabel.sizeToFit()
Чтобы ваш шрифт метки соответствовал ширине экрана или определенному размеру ширины.
myLabel.adjustsFontSizeToFitWidth = YES
и некоторая textAlignment для метки:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
Это старое решение, используйте автоматическое расположение на iOS> = 6
Мое решение:
@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