Respostas:
Não há como definir o alinhamento vertical em um UILabel
, mas você pode obter o mesmo efeito alterando o quadro do rótulo. Eu deixei minhas etiquetas em laranja para que você possa ver claramente o que está acontecendo.
Aqui está a maneira rápida e fácil de fazer isso:
[myLabel sizeToFit];
Se você tiver um rótulo com texto mais longo que formará mais de uma linha, defina numberOfLines
como 0
(zero aqui significa um número ilimitado de linhas).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Versão Longa
Farei meu rótulo no código para que você possa ver o que está acontecendo. Você também pode configurar a maior parte disso no Interface Builder. Minha configuração é um aplicativo baseado em exibição com uma imagem de fundo que fiz no Photoshop para mostrar margens (20 pontos). A etiqueta é uma cor laranja atraente, para que você possa ver o que está acontecendo com as dimensões.
- (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];
}
Algumas limitações do uso sizeToFit
entram em jogo com o texto alinhado ao centro ou à direita. Aqui está o que acontece:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
O rótulo ainda é dimensionado com um canto superior esquerdo fixo. Você pode salvar a largura da etiqueta original em uma variável e defini-la depois sizeToFit
ou fornecer uma largura fixa para combater esses problemas:
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;
Observe que sizeToFit
respeitará a largura mínima da sua etiqueta inicial. Se você começar com um rótulo com 100 de largura e chamar sizeToFit
, ele retornará um rótulo (possivelmente muito alto) com 100 (ou um pouco menos) de largura. Convém definir seu rótulo para a largura mínima desejada antes de redimensionar.
Algumas outras coisas a serem observadas:
Se lineBreakMode
é respeitado depende de como está definido. NSLineBreakByTruncatingTail
(o padrão) é ignorado depois sizeToFit
, assim como os outros dois modos de truncamento (cabeça e meio). NSLineBreakByClipping
também é ignorado. NSLineBreakByCharWrapping
funciona como de costume. A largura do quadro ainda é reduzida para caber na letra mais à direita.
Mark Amery deu uma correção para NIBs e Storyboards usando o Auto Layout nos comentários:
Se o seu marcador estiver incluído em uma ponta ou storyboard como uma
view
sub-visualização de um ViewController que usa o layout automático, asizeToFit
chamadaviewDidLoad
será feita não funcionará, porque o layout automático dimensiona e posiciona as sub-visualizações após aviewDidLoad
chamada e desfaz imediatamente os efeitos de seusizeToFit
ligar. No entanto, chamarsizeToFit
de dentroviewDidLayoutSubviews
vontade trabalho.
Isso usa o NSString
método sizeWithFont:constrainedToSize:lineBreakMode:
para calcular a altura do quadro necessária para ajustar uma sequência e, em seguida, define a origem e a largura.
Redimensione o quadro da etiqueta usando o texto que você deseja inserir. Dessa forma, você pode acomodar qualquer número de linhas.
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
, em seguida, usar SizeToFit em seguida, definir o quadro do rótulo para 0, 0, theWidthYouWant, label.frame.size.height (que é a nova altura determinada pela SizeToFit) em seguida, aplicaradjustsFontSizeToFitWidth
Defina o novo texto:
myLabel.text = @"Some Text"
Defina as maximum number
linhas como 0 (automático):
myLabel.numberOfLines = 0
Defina o quadro do rótulo para o tamanho máximo:
myLabel.frame = CGRectMake(20,20,200,800)
Ligue sizeToFit
para reduzir o tamanho do quadro e ajustar o conteúdo:
[myLabel sizeToFit]
O quadro de etiquetas agora é alto e largo o suficiente para caber no seu texto. O canto superior esquerdo deve permanecer inalterado. Eu testei isso apenas com o texto alinhado à esquerda superior. Para outros alinhamentos, pode ser necessário modificar o quadro posteriormente.
Além disso, meu rótulo tem quebra de linha ativada.
Referindo-se à solução de extensão:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
deve ser substituído por
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
É necessário espaço adicional em cada nova linha adicionada, porque UILabels
os retornos de carro à direita do iPhone parecem ser ignorados :(
Da mesma forma, alignBottom também deve ser atualizado com um @" \n@%"
no lugar de "\n@%"
(para a inicialização do ciclo deve ser substituída por "for (int i = 0 ..." também).
A seguinte extensão funciona para mim:
// -- 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
Em seguida, ligue [yourLabel alignTop];
ou [yourLabel alignBottom];
após cada atribuição de texto yourLabel.
VerticalAlign
entre parênteses depois @implementation UILabel
. Sendo novo no Objective-C, nunca encontrei essa sintaxe antes. Como isso é chamado?
sizeWithFont:constrainedToSize:lineBreakMode:
e sizeWithFont: são depreciados no iOS7. Além disso, esta categoria só funciona nos rótulos quando numberOfLines é maior que 0.
Caso isso ajude alguém, tive o mesmo problema, mas consegui resolver o problema simplesmente mudando de usar UILabel
para usar UITextView
. Compreendo que isso não seja para todos, porque a funcionalidade é um pouco diferente.
Se você mudar para o uso UITextView
, poderá desativar todas as propriedades da Visualização de rolagem, bem como a Interação do usuário ativada ... Isso o forçará a agir mais como um rótulo.
UITextView
me deu o resultado desejado imediatamente.
Sem confusão, sem confusão
@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
Sem confusão, sem Objective-c, sem confusão, mas 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)
}
}
Como a resposta acima, mas não era bem correta ou fácil de inserir código, então eu limpei um pouco. Adicione esta extensão ao seu próprio arquivo. He. Ou simplesmente cole logo acima da implementação que você pretende usar:
#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
E, para usar, coloque seu texto no rótulo e chame o método apropriado para alinhá-lo:
[myLabel alignTop];
ou
[myLabel alignBottom];
Uma maneira ainda mais rápida (e mais suja) de conseguir isso é definir o modo de quebra de linha do UILabel como "Clip" e adicionar uma quantidade fixa de novas linhas.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Esta solução não funcionará para todos - em particular, se você ainda deseja mostrar "..." no final da sua string, se exceder o número de linhas que você está mostrando, será necessário usar um dos os bits de código mais longos - mas, em muitos casos, você terá o que precisa.
UILineBreakModeWordWrap
vez disso.
Abordagem mais fácil usando o Storyboard:
Incorporar etiqueta no StackView e defina os seguintes dois atributos do StackView no Attribute Inspector:
1- Axis
aHorizontal
,
2- Alignment
aTop
UILabel
em alguma UIView
subclasse ( UIView
normalmente é o suficiente) e deixar esse rótulo crescer na direção descendente. Obrigado!
UILabel
e deixe a StackView fazer o seu trabalho. Obrigado!
Em vez de UILabel
você pode usar a UITextField
opção de alinhamento vertical:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Eu luto com esse problema há muito tempo e queria compartilhar minha solução.
Isso fornecerá um UILabel
texto que reduzirá automaticamente o texto a 0,5 escalas e centralizará o texto verticalmente. Essas opções também estão disponíveis no Storyboard / IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Crie uma nova classe
LabelTopAlign
arquivo .h
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
arquivo .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
Aqui está uma implementação mais simples que faz o mesmo:
#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
soluções isso realmente faz a UILabel
colocar qualquer texto na parte superior, mesmo se você substituir dinamicamente um texto mais curto com um mais longo, ou vice-versa.
No Interface Builder
UILabel
para o tamanho do maior texto possívelLines
como '0' no Inspetor de atributosNo seu código
sizeToFit
para sua etiquetaFragmento de código:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Para a UI adaptativa (iOS8 ou posterior), o Alinhamento vertical do UILabel deve ser definido no StoryBoard, alterando as propriedades
noOfLines
= 0` e
Restrições
Ajustando as restrições UILabel LefMargin, RightMargin e Top Margin.
Mude
Content Compression Resistance Priority For Vertical
= 1000` para que Vertical> Horizontal.
Editado:
noOfLines=0
e as seguintes restrições são suficientes para alcançar os resultados desejados.
Crie uma subclasse de UILabel. Funciona como um encanto:
// 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
Como discutido aqui .
Eu escrevi uma função util para atingir esse objetivo. Você pode dar uma olhada:
// ajusta a altura de uma etiqueta com várias linhas para alinhar verticalmente com a parte superior + (vazio) alignLabelWithTop: (UILabel *) rótulo { CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // obtém a altura real CGSize actualSize = [label.text sizeWithFont: label.font constrainedToSize: maxSize lineBreakMode: label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = actualSize.height; label.frame = rect; }
.Como usar? (Se lblHello for criado pelo construtor de interface, pulo alguns detalhes dos atributos do UILabel)
lblHello.text = @ "Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo! Olá Mundo!"; lblHello.numberOfLines = 5; [Utilitários alignLabelWithTop: lblHello];
Também escrevi no meu blog como um artigo: http://fstoke.me/blog/?p=2819
Demorei um pouco para ler o código, bem como o código na página apresentada, e descobri que todos eles tentavam modificar o tamanho do quadro do rótulo, para que o alinhamento vertical central padrão não aparecesse.
No entanto, em alguns casos, queremos que o rótulo ocupe todos esses espaços, mesmo que o rótulo tenha muito texto (por exemplo, várias linhas com a mesma altura).
Aqui, usei uma maneira alternativa de resolvê-lo, simplesmente preenchendo as novas linhas até o final do rótulo (observe que eu realmente herdei o UILabel
, mas não é necessário):
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 "];
}
Peguei as sugestões aqui e criei uma exibição que pode envolver um UILabel e dimensioná-lo e definir o número de linhas para que fique alinhado com o topo. Basta colocar um UILabel como uma subview:
@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
Você pode usar TTTAttributedLabel , ele suporta alinhamento vertical.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
Descobri que as respostas para esta pergunta estão um pouco desatualizadas, então adicione isso para os fãs de layout automático.
O layout automático torna esse problema bastante trivial. Supondo que estamos adicionando o rótulo a UIView *view
, o código a seguir fará isso:
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}]];
A altura da etiqueta será calculada automaticamente (usando-a intrinsicContentSize
) e a etiqueta será posicionada borda a borda horizontalmente, na parte superior da view
.
Eu usei muitos dos métodos acima e só quero adicionar uma abordagem rápida e suja que usei:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Verifique se o número de novas linhas na sequência fará com que qualquer texto preencha o espaço vertical disponível e defina o UILabel para truncar qualquer texto excedente.
Porque às vezes bom o suficiente é bom o suficiente .
UITextView
é que ela pode chamar dlopen
para suportar a entrada de texto. Isso pode causar um grande atraso no thread da interface do usuário, portanto, essa abordagem é muito mais eficiente!
Eu queria ter um rótulo capaz de ter várias linhas, um tamanho mínimo de fonte e centralizar horizontal e verticalmente na visualização principal. Adicionei meu rótulo programaticamente à minha exibição:
- (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];
}
E então, quando eu queria mudar o texto do meu rótulo ...
- (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];
}
Espero que ajude alguém!
O FXLabel (no github) faz isso imediatamente, configurando label.contentMode
para UIViewContentModeTop
. Este componente não é fabricado por mim, mas é um componente que uso com freqüência e possui muitos recursos e parece funcionar bem.
para quem estiver lendo isso porque o texto no seu rótulo não está centralizado verticalmente, lembre-se de que alguns tipos de fonte não são projetados igualmente. por exemplo, se você criar um rótulo com o tamanho 16 do zapfino, verá que o texto não está perfeitamente centralizado verticalmente.
no entanto, trabalhar com helvética centralizará verticalmente o seu texto.
Use textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Subclasse UILabel e restrinja o retângulo de desenho, assim:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Tentei a solução envolvendo o preenchimento de nova linha e, em alguns casos, tive um comportamento incorreto. Na minha experiência, é mais fácil restringir o desenho do retângulo do que mexer numberOfLines
.
PS Você pode imaginar facilmente dando suporte ao UIViewContentMode desta maneira:
- (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];
}
Contanto que você não esteja executando nenhuma tarefa complexa, poderá usar em UITextView
vez deUILabels
.
Desative a rolagem.
Se você deseja que o texto seja exibido completamente apenas o usuário sizeToFit
e os sizeThatFits:
métodos
Em rápido,
let myLabel : UILabel!
Para ajustar o texto do seu rótulo à tela e ele está no topo
myLabel.sizeToFit()
Para ajustar a fonte da etiqueta à largura da tela ou tamanho específico da largura.
myLabel.adjustsFontSizeToFitWidth = YES
e algum textAlignment para label:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
[myLabel sizeToFit]
. Obrigado!
Esta é uma solução antiga, use o autolayout no iOS> = 6
Minha solução:
@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