Respuestas:
No hay forma de establecer la alineación vertical en un UILabel
, pero puede obtener el mismo efecto cambiando el marco de la etiqueta. He hecho mis etiquetas de color naranja para que pueda ver claramente lo que está sucediendo.
Aquí está la manera rápida y fácil de hacer esto:
[myLabel sizeToFit];
Si tiene una etiqueta con texto más largo que hará más de una línea, establezca numberOfLines
en 0
(cero aquí significa un número ilimitado de líneas).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Versión más larga
Haré mi etiqueta en el código para que pueda ver lo que está sucediendo. También puede configurar la mayor parte de esto en Interface Builder. Mi configuración es una aplicación basada en la vista con una imagen de fondo que hice en Photoshop para mostrar los márgenes (20 puntos). La etiqueta es de un atractivo color naranja para que pueda ver qué sucede con las dimensiones.
- (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];
}
Algunas limitaciones de uso sizeToFit
entran en juego con texto alineado al centro o a la derecha. Esto es lo que pasa:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
La etiqueta todavía tiene el tamaño con una esquina superior izquierda fija. Puede guardar el ancho de la etiqueta original en una variable y configurarlo después sizeToFit
, o asignarle un ancho fijo para contrarrestar estos 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;
Tenga en cuenta que sizeToFit
respetará el ancho mínimo de su etiqueta inicial. Si comienza con una etiqueta de 100 de ancho y la llama sizeToFit
, le devolverá una etiqueta (posiblemente muy alta) con 100 (o un poco menos) de ancho. Es posible que desee establecer su etiqueta al ancho mínimo que desea antes de cambiar el tamaño.
Algunas otras cosas a tener en cuenta:
Si lineBreakMode
se respeta depende de cómo se establece. NSLineBreakByTruncatingTail
(el valor predeterminado) se ignora después sizeToFit
, al igual que los otros dos modos de truncamiento (head y middle). NSLineBreakByClipping
También se ignora. NSLineBreakByCharWrapping
Funciona como siempre. El ancho del marco todavía se reduce para ajustarse a la letra más a la derecha.
Mark Amery dio una solución para NIBs y Storyboards usando Auto Layout en los comentarios:
Si su etiqueta se incluye en una plumilla o guión gráfico como una subvista de
view
un ViewController que utiliza la distribución automática, entonces poner susizeToFit
llamada enviewDidLoad
no funcionará, porque el tamaño de la distribución automática y las posiciones de las subvistas despuésviewDidLoad
se llama e inmediatamente deshacerá los efectos de susizeToFit
llamada. Sin embargo, llamandosizeToFit
desde dentro deviewDidLayoutSubviews
la voluntad de trabajo.
Utiliza el NSString
método sizeWithFont:constrainedToSize:lineBreakMode:
para calcular la altura del marco necesaria para ajustar una cadena, luego establece el origen y el ancho.
Cambie el tamaño del marco para la etiqueta usando el texto que desea insertar. De esa manera puede acomodar cualquier número de líneas.
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
, use sizeToFit y luego configure el marco de la etiqueta en 0, 0, theWidthYouWant, label.frame.size.height (que es la nueva altura determinada por sizeToFit) LUEGO apliqueadjustsFontSizeToFitWidth
Establecer el nuevo texto:
myLabel.text = @"Some Text"
Establezca las maximum number
líneas en 0 (automático):
myLabel.numberOfLines = 0
Establezca el marco de la etiqueta al tamaño máximo:
myLabel.frame = CGRectMake(20,20,200,800)
Llame sizeToFit
para reducir el tamaño del marco para que el contenido se ajuste:
[myLabel sizeToFit]
El marco de las etiquetas ahora es lo suficientemente alto y ancho como para adaptarse a su texto. La parte superior izquierda no debe modificarse. He probado esto solo con el texto alineado a la izquierda superior. Para otras alineaciones, es posible que deba modificar el marco después.
Además, mi etiqueta tiene habilitado el ajuste de texto.
Refiriéndose a la solución de extensión:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
debe ser reemplazado por
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
Se necesita espacio adicional en cada nueva línea agregada, porque UILabels
parece que se ignora el retorno del carro posterior del iPhone :(
Del mismo modo, alignBottom también debe actualizarse con un @" \n@%"
en lugar de "\n@%"
(para la inicialización del ciclo debe reemplazarse por "for (int i = 0 ..." también).
La siguiente extensión funciona para mí:
// -- 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
Luego llame [yourLabel alignTop];
o [yourLabel alignBottom];
después de cada asignación de texto yourLabel.
VerticalAlign
entre paréntesis después @implementation UILabel
. Al ser nuevo en Objective-C, no me he encontrado con esta sintaxis antes. ¿Como se llama esto?
sizeWithFont:constrainedToSize:lineBreakMode:
y sizeWithFont: se deprecian en iOS7. Además, esta categoría solo funciona en etiquetas cuando numberOfLines es mayor que 0.
En caso de que sea de alguna ayuda para alguien, tuve el mismo problema pero pude resolver el problema simplemente cambiando de usar UILabel
a usar UITextView
. Aprecio que esto no sea para todos porque la funcionalidad es un poco diferente.
Si cambia al uso UITextView
, puede desactivar todas las propiedades de la Vista de desplazamiento, así como la Interacción del usuario habilitada ... Esto lo obligará a actuar más como una etiqueta.
UITextView
me dio el resultado deseado de inmediato.
Sin despeinarse sin problemas
@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
Sin muss, sin Objective-c, sin problemas, pero 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)
}
}
Me gusta la respuesta anterior, pero no estaba del todo bien, o fue fácil introducir el código, así que lo limpié un poco. Agregue esta extensión a su propio archivo .h y .m o simplemente péguelo justo encima de la implementación que desea 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
Y luego, para usar, coloque el texto en la etiqueta y luego llame al método apropiado para alinearlo:
[myLabel alignTop];
o
[myLabel alignBottom];
Una forma aún más rápida (y más sucia) de lograr esto es estableciendo el modo de salto de línea de UILabel en "Clip" y agregando una cantidad fija de líneas nuevas.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Esta solución no funcionará para todos, en particular, si aún desea mostrar "..." al final de su cadena si excede el número de líneas que está mostrando, deberá usar una de los bits más largos de código, pero para muchos casos esto le dará lo que necesita.
UILineBreakModeWordWrap
lugar.
Enfoque más fácil usando Storyboard:
Incrustar la etiqueta en StackView y conjunto tras dos atributos de StackView en Atributo Inspector:
1- Axis
a Horizontal
,
2- Alignment
aTop
UILabel
en alguna UIView
subclase ( UIView
normalmente es simple ) y dejar que esa etiqueta crezca hacia abajo. ¡Gracias!
UILabel
y dejar que el StackView haga su trabajo. ¡Gracias!
En lugar de UILabel
usted, puede usar el UITextField
que tiene la opción de alineación vertical:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
He tenido problemas con este durante mucho tiempo y quería compartir mi solución.
Esto le dará una UILabel
reducción automática del texto a 0.5 escalas y centrará verticalmente el texto. Estas opciones también están disponibles en Storyboard / IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Crea una nueva clase
LabelTopAlign
archivo .h
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
archivo .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
Aquí hay una implementación más simple que hace lo mismo:
#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
soluciones de esta realidad hace que el UILabel
poner cualquier texto en la parte superior, incluso si cambia dinámicamente un texto corto con uno más largo o viceversa.
En Interface Builder
UILabel
tamaño del texto más grande posibleLines
en '0' en el Inspector de atributosEn su código
sizeToFit
a su etiquetaFragmento de código:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Para la IU adaptativa (iOS8 o posterior), la Alineación vertical de UILabel se configurará desde StoryBoard cambiando las propiedades
noOfLines
= 0` y
Restricciones
Ajuste de las restricciones UILabel LefMargin, RightMargin y Top Margin.
Cambio
Content Compression Resistance Priority For Vertical
= 1000` Para que Vertical> Horizontal.
Editado:
noOfLines=0
y las siguientes restricciones son suficientes para lograr los resultados deseados.
Crea una subclase de UILabel. Funciona de maravilla:
// 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 se discutió aquí .
Escribí una función util para lograr este propósito. Puedes echar un vistazo:
// ajusta la altura de una etiqueta de varias líneas para alinearla verticalmente con la parte superior + (vacío) alignLabelWithTop: etiqueta (UILabel *) { CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // obtener la altura real CGSize actualSize = [label.text sizeWithFont: label.font restrictinedToSize: maxSize lineBreakMode: label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = actualSize.height; label.frame = rect; }
.¿Cómo utilizar? (Si lblHello es creado por el generador de interfaces, entonces omito algunos detalles de los atributos de UILabel)
lblHello.text = @ "¡Hola mundo! ¡Hola mundo! ¡Hola mundo! ¡Hola mundo! ¡Hola mundo! ¡Hola mundo! ¡Hola mundo! ¡Hola mundo!"; lblHello.numberOfLines = 5; [Utilidades alignLabelWithTop: lblHello];
También lo escribí en mi blog como un artículo: http://fstoke.me/blog/?p=2819
Me tomó un tiempo leer el código, así como el código en la página introducida, y descubrí que todos intentan modificar el tamaño del marco de la etiqueta, para que no aparezca la alineación vertical central predeterminada.
Sin embargo, en algunos casos queremos que la etiqueta ocupe todos esos espacios, incluso si la etiqueta tiene mucho texto (por ejemplo, varias filas con la misma altura).
Aquí, utilicé una forma alternativa de resolverlo, simplemente rellenando las nuevas líneas hasta el final de la etiqueta (tenga en cuenta que en realidad heredé el UILabel
, pero no es necesario):
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 "];
}
Tomé las sugerencias aquí y creé una vista que puede envolver un UILabel y lo dimensionará y establecerá el número de líneas para que quede alineado en la parte superior. Simplemente ponga un UILabel como una subvista:
@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
Puede usar TTTAttributedLabel , es compatible con la alineación vertical.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
He encontrado que las respuestas a esta pregunta ahora están un poco desactualizadas, por lo que agrego esto para los fanáticos del diseño automático.
El diseño automático hace que este problema sea bastante trivial. Suponiendo que agreguemos la etiqueta UIView *view
, el siguiente código logrará esto:
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}]];
La altura de la etiqueta se calculará automáticamente (usando su intrinsicContentSize
) y la etiqueta se colocará de borde a borde horizontalmente, en la parte superior de la etiqueta view
.
He usado muchos de los métodos anteriores, y solo quiero agregar un enfoque rápido y sucio que he usado:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Asegúrese de que el número de líneas nuevas en la cadena hará que cualquier texto llene el espacio vertical disponible y configure UILabel para truncar cualquier texto que se desborde.
Porque a veces lo suficientemente bueno es lo suficientemente bueno .
UITextView
es que puede llamar dlopen
para admitir la entrada de texto. Esto puede causar un gran retraso en el hilo de la interfaz de usuario, por lo que este enfoque es mucho más eficaz.
Quería tener una etiqueta que pudiera tener líneas múltiples, un tamaño de fuente mínimo y centrada tanto horizontal como verticalmente en su vista principal. Agregué mi etiqueta mediante programación a mi vista:
- (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];
}
Y luego, cuando quería cambiar el texto de mi etiqueta ...
- (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 ayude a alguien!
FXLabel (en github) hace esto fuera de la caja estableciendo label.contentMode
en UIViewContentModeTop
. Este componente no está hecho por mí, pero es un componente que uso con frecuencia y tiene toneladas de características, y parece funcionar bien.
Para cualquiera que lea esto porque el texto dentro de su etiqueta no está centrado verticalmente, tenga en cuenta que algunos tipos de fuente no están diseñados de la misma manera. por ejemplo, si crea una etiqueta con zapfino tamaño 16, verá que el texto no está perfectamente centrado verticalmente.
sin embargo, trabajar con helvetica centrará verticalmente su texto.
Uso textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Subclase UILabel y restrinja el rectángulo de dibujo, así:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Probé la solución que implica el relleno de nueva línea y encontré un comportamiento incorrecto en algunos casos. En mi experiencia, es más fácil restringir el dibujo correcto que el anterior que meterse con él numberOfLines
.
PD: puede imaginarse fácilmente apoyando UIViewContentMode de esta manera:
- (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];
}
Mientras no esté haciendo ninguna tarea compleja, puede usarla en UITextView
lugar de UILabels
.
Desactiva el desplazamiento.
Si desea que el texto se muestre completamente solo usuario sizeToFit
y sizeThatFits:
métodos
En rápido,
let myLabel : UILabel!
Para que el texto de su etiqueta se ajuste a la pantalla y esté en la parte superior
myLabel.sizeToFit()
Para que su fuente de etiqueta se ajuste al ancho de la pantalla o al tamaño de ancho específico.
myLabel.adjustsFontSizeToFitWidth = YES
y algo de texto Alineación para la etiqueta:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
[myLabel sizeToFit]
. ¡Gracias!
Esta es una solución antigua, use el autolayout en iOS> = 6
Mi solución:
@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