Ответы:
Там нет никакого способа установить вертикальное выравнивание на 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
, как и два других режима усечения (head и middle). 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;
adjustsFontSizeToFitWidth
используйте sizeToFit, затем установите для фрейма метки значение 0, 0, theWidthYouWant, label.frame.size.height (это новая высота, определяемая sizeToFit). Затем применитеadjustsFontSizeToFitWidth
Установите новый текст:
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 "];
В каждой добавленной новой строке необходимо дополнительное место, потому что UILabels
возврат каретки в iPhone, похоже, игнорируется :(
Аналогично, 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.
VerticalAlign
между скобками после @implementation UILabel
. Будучи новичком в Objective-C, я не сталкивался с этим синтаксисом раньше. Как это называется?
sizeWithFont:constrainedToSize:lineBreakMode:
и sizeWithFont: оба устарели в iOS7. Кроме того, эта категория работает только для меток, когда numberOfLines больше 0.
На всякий случай, если это кому-нибудь поможет, у меня возникла та же проблема, но я смог решить ее, просто переключившись с использования UILabel
на использование UITextView
. Я ценю это не для всех, потому что функциональность немного отличается.
Если вы переключитесь на использование 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 значение «Клип» и добавить фиксированное количество новых строк.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Это решение не будет работать для всех - в частности, если вы все еще хотите показывать «...» в конце вашей строки, если оно превышает количество отображаемых строк, вам нужно использовать одну из более длинные фрагменты кода - но во многих случаях это даст вам то, что вам нужно.
UILineBreakModeWordWrap
вместо этого.
Самый простой подход с использованием раскадровки:
Вставить метку в StackView и набор следующих двух атрибутов StackView в Attribute Inspector:
1- Axis
доHorizontal
,
2- Alignment
доTop
UILabel
в некоторый UIView
подкласс ( UIView
обычно достаточно простого ) и позволить этой метке расти в направлении вниз. Спасибо!
UILabel
и позволить StackView делать свою работу. Спасибо!
Вместо этого UILabel
вы можете использовать UITextField
вариант с вертикальным выравниванием:
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
sizeToFit
решений , это фактически делает UILabel
положить любой текст в верхней части, даже если вы динамически заменить более короткий текст с более одной или наоборот.
В Интерфейсном Разработчике
UILabel
размер максимально возможного текстаLines
в '0' в Инспекторе АтрибутовВ вашем коде
sizeToFit
на свой лейблФрагмент кода:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Для Adaptive UI (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 "];
}
Я взял предложения здесь и создал представление, которое может обернуть 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's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Я обнаружил, что ответы на этот вопрос сейчас немного устарели, поэтому добавлю их для поклонников автоматического макета.
Авто макет делает этот вопрос довольно тривиальным. Предполагая, что мы добавляем метку 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 для усечения любого переполненного текста.
Потому что иногда достаточно хорошо, достаточно хорошо .
UITextView
это то, что он может вызывать dlopen
для поддержки ввода текста. Это может вызвать серьезную задержку в потоке пользовательского интерфейса, поэтому этот подход намного эффективнее!
Я хотел иметь метку, которая могла бы иметь несколько строк, минимальный размер шрифта и центрироваться как по горизонтали, так и по вертикали в родительском представлении. Я добавил мой ярлык программно на мой взгляд:
- (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];
}
Надеюсь, что это помогает кому-то!
FXLabel (на github) делает это из коробки, установив label.contentMode
в UIViewContentModeTop
. Этот компонент сделан не мной, но это компонент, который я часто использую, имеет множество функций и, кажется, работает хорошо.
для тех, кто читает это, потому что текст внутри вашего ярлыка не центрирован по вертикали, имейте в виду, что некоторые типы шрифтов не разработаны одинаково. например, если вы создадите метку с размером zapfino 16, вы увидите, что текст не идеально отцентрирован по вертикали.
тем не менее, работа с helvetica будет центрировать ваш текст по вертикали.
Использование textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Подкласс 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];
}
Пока вы не выполняете никаких сложных задач, вы можете использовать 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
[myLabel sizeToFit]
. Спасибо!
Это старое решение, используйте автоматическое расположение на 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