Відповіді:
Неможливо встановити вертикальне вирівнювання на a 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
, як і інші два режими усікання (голова та середина). NSLineBreakByClipping
також ігнорується. NSLineBreakByCharWrapping
працює як завжди. Ширина рамки все ще звужується, щоб підходити до правої літери.
Марк Амері в коментарях дав виправлення для НІБ та Дошка розказок, використовуючи функцію автоматичного макета:
Якщо ваша мітка включена в підказку або дошку розкадрувань як підзагляд програми
view
ViewController, яка використовує автоматичну розкладку, то введення вашогоsizeToFit
дзвінкаviewDidLoad
не буде працювати, оскільки виклик автоматичного розкладу та розміщення після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@%"
замість a "\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];
після кожного призначення тексту мітки.
VerticalAlign
між дужками після @implementation UILabel
. Будучи новинкою в Objective-C, я раніше не стикався з цим синтаксисом. Як це називається?
sizeWithFont:constrainedToSize:lineBreakMode:
та розмірWithFont: обидва амортизуються в iOS7. Також ця категорія працює лише на етикетках, коли числоOfLines перевищує 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)
}
}
Швидкий 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 в інспекторі атрибутів:
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 масштабу та вертикального центру центру. Ці параметри також доступні в Storyboard / 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
ставити будь-який текст у верхній частині, навіть якщо ви динамічно замінюєте коротший текст більш довгим чи навпаки.
У програмі Interface Builder
UILabel
розмір найбільшого можливого текстуLines
інспекторі атрибутів встановіть значення "0"У своєму коді
sizeToFit
на свою етикеткуФрагмент коду:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Для адаптивного інтерфейсу (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
Як обговорювалося тут .
Я написав функцію util для досягнення цієї мети. Ви можете поглянути:
// регулюйте висоту багаторядкової мітки, щоб вона вирівнювалась вертикально з верхом + (недійсна) alignLabelWithTop: (UILabel *) мітка { CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = НІ; // отримати фактичну висоту CGSize фактичний розмір = [label.text sizeWithFont: label.font constrainedToSize: maxSize lineBreakMode: label.lineBreakMode]; CGRect rect = label.frame; rect.size.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; [Утиліти вирівнятиLabelWithTop: lblHello];
Я також написав це у своєму блозі як статтю: http://fstoke.me/blog/?p=2819
Я зайняв деякий час, щоб прочитати код, а також код на введеній сторінці, і виявив, що всі вони намагаються змінити розмір кадру етикетки, щоб не з’явилося вертикальне вирівнювання по центру за замовчуванням.
Однак у деяких випадках ми хочемо, щоб мітка займала всі ці пробіли, навіть якщо в мітці є стільки тексту (наприклад, кілька рядків з однаковою висотою).
Тут я використав альтернативний спосіб її вирішення, просто проклавши нові рядки до кінця мітки (pls зауважте, що я насправді успадкував 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
і деякі текстові налаштування для мітки:
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