Alinear verticalmente el texto hacia la parte superior dentro de un UILabel

Tengo un UILabel con espacio para dos líneas de texto. A veces, cuando el texto es demasiado corto, este texto se muestra en el centro vertical de la etiqueta.

¿Cómo alineo verticalmente el texto para que esté siempre en la parte superior del UILabel?

imagen que representa un UILabel con texto centrado verticalmente

preguntado el 28 de junio de 09 a las 05:06

30 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. Hice mis etiquetas de color naranja para que pueda ver claramente lo que está sucediendo.

Esta es la forma rápida y sencilla de hacer esto:

    [myLabel sizeToFit];

sizeToFit para apretar una etiqueta


Si tiene una etiqueta con texto más largo que formará más de una línea, configure numberOfLines a 0 (cero aquí significa un número ilimitado de líneas).

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

Texto de etiqueta más largo con sizeToFit


Versión más larga

Haré mi etiqueta en código para que puedas ver lo que está pasando. También puede configurar la mayor parte de esto en Interface Builder. Mi configuración es una aplicación basada en vistas con una imagen de fondo que hice en Photoshop para mostrar márgenes (20 puntos). La etiqueta es de un atractivo color naranja para que pueda ver lo que 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 en el centro o la derecha. Esto es lo que sucede:

    // myLabel.textAlignment = NSTextAlignmentRight;
    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

enter image description here

La etiqueta todavía tiene un 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 darle 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;

alineación de etiquetas


Tenga en cuenta que sizeToFit respetará el ancho mínimo de su etiqueta inicial. Si comienza con una etiqueta de 100 de ancho y llama sizeToFit en él, le devolverá una etiqueta (posiblemente muy alta) con 100 (o un poco menos) de ancho. Es posible que desee configurar su etiqueta al ancho mínimo que desee antes de cambiar el tamaño.

Corrija la alineación de la etiqueta cambiando el tamaño del ancho del marco

Algunas otras cosas a tener en cuenta:

Ya sea lineBreakMode se respeta depende de cómo se establezca. NSLineBreakByTruncatingTail (el valor predeterminado) se ignora después sizeToFit, al igual que los otros dos modos de truncamiento (principal y medio). NSLineBreakByClipping también se ignora. NSLineBreakByCharWrapping funciona como de costumbre. El ancho del marco aún se reduce para ajustarse a la letra más a la derecha.


marca amery dio una solución para NIB y Storyboards usando Auto Layout en los comentarios:

Si su etiqueta está incluida en una plumilla o guión gráfico como una subvista del view de un ViewController que usa autolayout, luego colocando su sizeToFit llamar a viewDidLoad no funcionará, porque el diseño automático dimensiona y posiciona las subvistas después viewDidLoad se llama y deshará inmediatamente los efectos de su sizeToFit llamada. Sin embargo, llamando sizeToFit desde adentro viewDidLayoutSubviews trabajo.


Mi respuesta original (para posteridad / referencia):

Esto usa 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 de la etiqueta utilizando el texto que desea insertar. De esa forma, 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;

Respondido 11 Oct 19, 13:10

necesitas eliminar el diseño automático - colgadobm06

He aquí una forma sencilla de resolver el problema: stackoverflow.com/a/26632490/636559 - AboulEinein

Si usa el diseño automático y el guión gráfico, agregar una restricción con la opción "Eliminar en el momento de la compilación" marcada ayudará: JK ABC

Esta respuesta es innecesariamente complicada y usa una "palabra alrededor". Consulte la sugerencia a continuación de simplemente cambiar la prioridad de abrazo de contenido vertical. No requiere ningún código ... - abeja

Aún puede usar Autodiseño y restricciones, pero asegúrese de que la [altura] no será fija. Por ejemplo: establezca Izquierda, Superior y Derecha en 8 px, pero Inferior puede establecer "Mayor o igual" 8 px. Le dirá a iOS, deje que mi sizeToFit decida la mejor altura para mi etiqueta. - orafaelreis

  1. Establecer el nuevo texto:

    myLabel.text = @"Some Text"
    
  2. Seleccione las maximum number de líneas a 0 (automático):

    myLabel.numberOfLines = 0
    
  3. Establezca el marco de la etiqueta en el tamaño máximo:

    myLabel.frame = CGRectMake(20,20,200,800)
    
  4. Llame al sizeToFit para reducir el tamaño del marco para que el contenido simplemente quepa:

    [myLabel sizeToFit]
    

El marco de las etiquetas ahora es lo suficientemente alto y ancho para adaptarse a su texto. La parte superior izquierda no debe modificarse. He probado esto solo con el texto alineado en la parte superior izquierda. Para otras alineaciones, es posible que deba modificar el marco posteriormente.

Además, mi etiqueta tiene habilitado el ajuste de palabras.

Respondido 11 Oct 19, 13:10

Hola Ben, volví a mirar mi código anterior y actualicé mi respuesta con los pasos correctos necesarios. - jakob egger

Esto funcionó bien para mi. Configuré las dimensiones de mi UILabel y cambié numberOfLines a 0 en IB y luego después de configurar el texto llamado [myLabel sizeToFit]. - Dan Ellis

funciona perfectamente para mí, después de establecer el número de líneas en Attr. Inspector - d2burke

No funciona en caso de un número de líneas superior a 1 - tom

No funciona cuando desea una etiqueta de dos líneas, pero el texto requiere más líneas. - José Manuel Abarca Rodríguez

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 el iPhone UILabels'Los retornos de carro finales parecen ignorarse :(

Del mismo modo, alignBottom también debería 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 me funciona:

// -- 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]; or [yourLabel alignBottom]; después de cada asignación de texto de yourLabel.

Respondido 29 Abr '13, 06:04

@DS noté que estás agregando VerticalAlign entre paréntesis después de @implementation UILabel. Siendo nuevo en Objective-C, no me he encontrado con esta sintaxis antes. ¿Como se llama esto? - Juliano

Increíble, no sabía de categorías, esto me da aún más aprecio por el lenguaje Objective-c. Aprender más idiomas es muy importante para convertirse en un buen programador. - JeroenEijkhof

Dio un voto a favor. pero iirc, esto no funcionará si no conoce la cantidad de líneas, lo cual es una desventaja: Tjirp

Tengo que mostrar 3 líneas de texto y alinear el texto en la parte superior. Entonces, ¿debo establecer el número de líneas en 3. Cuando lo configuro en 3, veo "..." si el texto es menor (que cabe en una línea). Cómo evitar este "..." - Satyam

Publiqué una edición de esta categoría, espero que sea aprobada en breve. Los métodos sizeWithFont:constrainedToSize:lineBreakMode: y sizeWithFont: ambos se deprecian en iOS7. Además, esta categoría solo funciona en etiquetas cuando numberOfLines es mayor que 0. - Timgcarlson

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 la utilización de UITextView. Aprecio que esto no es para todos porque la funcionalidad es un poco diferente.

Si cambia a usar 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.

enter image description here

Respondido 12 ago 15, 15:08

No estoy seguro de cómo afectará esto al rendimiento si muchas UILabels se convierten en vistas de texto. - ninja

Todas las otras soluciones en este hilo no funcionaron para mí en iOS 7 (por el motivo que sea). Pero simplemente usando un UITextView me dio el resultado deseado de inmediato. - Clifton Labrum

Es una solución alternativa, todavía necesita algunos ajustes para que parezca auténtico, pero de hecho, esta es la solución sin código más fácil que vi, aprobado. - Itai Spector

Me gusta esta solucion. Por supuesto, puede haber problemas de rendimiento y tal, para una etiqueta simple en una vista relativamente simple, esto fue perfecto para lo que necesitaba (y no puedo notar ningún impacto en el rendimiento). JCutting8

Un pequeño inconveniente de este método es que introducirá un relleno intrínseco adicional al texto. Una solución rápida es introducir una restricción negativa. - sira lam

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 despeinarse, 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)
    }

}

Respondido 11 Oct 19, 13:10

¡La versión rápida me funcionó sin efectos secundarios! ¡Buen trabajo! - vasilev

Probablemente la mejor respuesta aquí, funciona en todos los escenarios. sizeToFit no funciona si la etiqueta está en UITableviewCell. Buen trabajo. - Rajat Chauhan

También funciona muy bien con AutoLayout. ¡Gracias! - Kushagra

Como la respuesta anterior, pero no era del todo correcta o fácil de insertar en el código, así que lo limpié un poco. Agregue esta extensión a su propio archivo .hy .m o simplemente péguela 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 su texto en la etiqueta y luego llame al método apropiado para alinearlo:

[myLabel alignTop];

or

[myLabel alignBottom];

respondido 05 mar '12, 21:03

sizeWithFont obsoleto - tdios

El enfoque más fácil con Storyboard:

Insertar etiqueta en un vista de pila y establezca los siguientes dos atributos de StackView en Attribute Inspector:

1- Axis a Horizontal,

2- Alignment a Top

enter image description here

Respondido el 08 de Septiembre de 20 a las 08:09

Para obtener mejores resultados, puede hacer esto StackView> Ver> UILabel, porque cuando simplemente inserta un UILabel dentro de un StackView, el StackView cambia de tamaño para ajustar UILabel al tamaño mínimo - Daniel Beltrami

Gran idea para colocar UILabel en algunos UIView subclase (llano UIView suele ser suficiente) y deje que la etiqueta crezca hacia abajo. ¡Gracias! - Victor Kucera

¡Impresionante! También vale la pena mencionar que necesitas limitaciones claras al UILabel y deje que StackView haga su trabajo. ¡Gracias! - luiz dias

Con el comando de menú Editor-> Incrustar con su etiqueta seleccionada, Xcode borra las restricciones de las etiquetas, luego puede establecer las restricciones para StackView. Este enfoque está más cerca de un enfoque de diseño 'SwiftUI', que es como lo descubrí. - Jardín de cohetes

Una forma aún más rápida (y más sucia) de lograr esto es configurando el modo de salto de línea de UILabel en "Clip" y agregando una cantidad fija de nuevas líneas.

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 uno de los bits más largos de código, pero en muchos casos esto le dará lo que necesita.

Respondido 18 Abr '10, 22:04

Configurar el modo de salto de línea en 'clip' parece estropear el tamaño automático de la etiqueta. Usar UILineBreakModeWordWrap en lugar de. - Niels van der Rest

y mejor agregue espacios "\ n \ n" - djdance

En lugar de UILabel puedes utilizar UITextField que tiene la opción de alineación vertical:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

Respondido 10 Feb 12, 10:02

Advertencia: UITextField solo permite una sola línea de texto. - David James

Para completar el comentario de @DavidJames: UITextView sería más apropiado - cedricsoubrie

He luchado con este durante mucho tiempo y quería compartir mi solución.

Esto te dará una UILabel que reducirá automáticamente el texto a escalas 0.5 y lo centrará verticalmente. Estas opciones también están disponibles en Storyboard / IB.

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

Respondido 08 ago 13, 13:08

Funcionó como perfecto entre todas las respuestas proporcionadas. Gracias @David Greco. Junto con estas propiedades, si establecemos adjustsFontSizeToFitWidth en YES, el texto se ajustará al marco sin modificar el marco de la etiqueta. - Ashok

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

Editar

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

Respondido 11 Feb 13, 23:02

+1 para la respuesta real. A diferencia del sizeToFit soluciones esto en realidad hace que el UILabel poner cualquier texto en la parte superior, incluso si reemplaza dinámicamente un texto más corto por uno más largo o viceversa. - Serpiente

enter image description here

En Interface Builder

  • Kit UILabel al tamaño del texto más grande posible
  • Kit Lines a '0' en el inspector de atributos

En tu código

  • Establecer el texto de la etiqueta
  • Llame al sizeToFit en tu etiqueta

Fragmento de código:

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];

Respondido 29 Abr '13, 06:04

funcionó muy bien, excepto en mi caso que necesitaba establecer las líneas en 2: tener un UILabel dentro de un UITableViewCell y configurarlo en 0 hizo que se superpusiera, pero configurarlo en 2 funcionó (la celda tiene suficiente espacio para 2 líneas) - eselk

Para la interfaz de usuario adaptable (iOS8 o posterior), la alineación vertical de UILabel se debe configurar desde StoryBoard cambiando las propiedades noOfLines= 0` y

Limitaciones

  1. Ajuste de las restricciones de UILabel LefMargin, RightMargin y Top Margin.

  2. Cambiar Content Compression Resistance Priority For Vertical= 1000` Entonces, Vertical> Horizontal.

Restricciones de UILabel

Editado:

noOfLines=0

y las siguientes limitaciones son suficientes para lograr los resultados deseados.

enter image description here

Respondido 22 ago 15, 23:08

Esto fue asombroso. ¿Puede explicar por qué Vertical> Horizontal hizo el trabajo? Gracias. - Gabriel

Cree 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 discutio aquí.

Respondido 14 Jul 11, 15:07

Escribí una función útil para lograr este propósito. Puedes echar un vistazo:

// ajusta la altura de una etiqueta de varias líneas para que se alinee verticalmente con la parte superior + (void) alignLabelWithTop: (UILabel *) label {CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // obtener la 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; }

.¿Cómo utilizar? (Si lblHello es creado por el generador de interfaces, 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; [Utils alignLabelWithTop: lblHello];

También lo escribí en mi blog como artículo: http://fstoke.me/blog/?p=2819

contestado el 23 de mayo de 11 a las 09:05

Me tomé un tiempo para leer el código, así como el código en la página introducida, y descubrí que todos intentaban modificar el tamaño del marco de la etiqueta, de modo que no apareciera 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 líneas nuevas 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 "];
}

Respondido 10 Jul 13, 10:07

Lo que hice en mi aplicación fue establecer la propiedad de línea de UILabel en 0, así como crear una restricción inferior de UILabel y asegurarme de que esté configurada en> = 0 como se muestra en la imagen a continuación. enter image description here

contestado el 19 de mayo de 18 a las 14:05

No tengo idea de por qué esta no es la respuesta aceptada. Mucho más simple que el que es. ¡Buena respuesta! - desarrollador de Android

La mejor respuesta. Ningún código en absoluto. - andron

¡Sí! Esto es lo que estaba buscando. Esta debería ser la respuesta aceptada. - Ensar Bayhan

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 esté alineado en la parte superior. Simplemente coloque 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

Respondido el 14 de diciembre de 10 a las 01:12

Puedes usar el TTTAttributedLabel, admite alineación vertical.

@property (nonatomic) TTTAttributedLabel* label;
<...>

//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;

Respondido 18 Feb 15, 09:02

Utiliza textRect(forBounds:limitedToNumberOfLines:).

class TopAlignedLabel: UILabel {
  override func drawText(in rect: CGRect) {
    let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
    super.drawText(in: textRect)
  }
}

Respondido el 05 de diciembre de 20 a las 16:12

¡Usted señor es un dios! - Diogo Antunes

Esta respuesta debería obtener mucho más votos positivos ya que es, con mucho, la solución más agradable y limpia. - Michael Ochs

La mejor respuesta, ¡funciona perfecto! - Massimo Pavanel

Gracias a todos. :-) - ma11hew28

Qué lindo. Me llevó a la dirección correcta para centrar verticalmente mi etiqueta. - leo dabus

Encontré 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 a 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 view.

Respondido 29 Abr '14, 02:04

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 desbordado.

Porque a veces lo suficientemente bueno es lo suficientemente bueno.

Respondido 30 ago 15, 18:08

Sin embargo, dada la variación en las alturas del tamaño de la pantalla de los dispositivos iOS, entonces debería haber un número variable de '\ n' para tener en cuenta el cambio de altura de uilabel (que es una posibilidad). Por tanto, este método no es particularmente útil a largo plazo. - Rambatino

Nota: "rápido y sucio" no es la "solución perfecta para todos los tiempos". Sólo digo'. - Código Roadie

@CodeRoadie Rápido y sucio me sirvió, tuve un par de problemas de diseño con la respuesta real. Podría hacerlo de la "manera correcta", ¡pero gracias por ahorrarme algo de tiempo! - Séraphin Hochart

@dGambit, tenga en cuenta: "rápido y sucio"- Código Roadie

Algo que aprendí recientemente al cargar vistas dinámicamente con UITextView es que puede llamar dlopen para admitir la entrada de texto. Esto puede causar un retraso importante en el hilo de la interfaz de usuario, por lo que este enfoque es mucho más eficaz. - yano

Quería tener una etiqueta que pudiera tener varias líneas, un tamaño de fuente mínimo y centrada tanto horizontal como verticalmente en su vista principal. Agregué mi etiqueta programáticamente 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 quise 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!

Respondido el 14 de Septiembre de 10 a las 02:09

FXLabel (en github) hace esto fuera de la caja configurando label.contentMode a 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.

Respondido el 15 de junio de 15 a las 22:06

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.

respondido 01 mar '11, 00:03

Muchas fuentes personalizadas no están alineadas verticalmente al centro. UILabel o UITextView siempre están alineados verticalmente al centro. No es necesario pensar en la alineación vertical en la programación de iOS. - Amit Singh

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 involucra 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 rect como arriba que meterse con numberOfLines.

PD: Puedes imaginar fácilmente admitir 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];
}

Respondido 03 Jul 12, 17:07

Si está utilizando el diseño automático, establezca el contentHuggingPriority vertical en 1000, ya sea en código o IB. En IB, es posible que deba eliminar una restricción de altura estableciendo su prioridad en 1 y luego eliminándola.

Respondido el 05 de Septiembre de 13 a las 17:09

Siempre que no esté realizando ninguna tarea compleja, puede utilizar UITextView en lugar de UILabels.

Desactive el desplazamiento.

Si desea que el texto se muestre completamente solo usuario sizeToFit y sizeThatFits: métodos

Respondido 02 Jul 15, 11:07

En rápido

let myLabel : UILabel!

Para hacer que el texto de su etiqueta se ajuste a la pantalla y esté en la parte superior

myLabel.sizeToFit()

Para hacer que la fuente de la etiqueta se ajuste al ancho de la pantalla o al tamaño de ancho específico.

myLabel.adjustsFontSizeToFitWidth = YES

y algo de textAlignment para la etiqueta:

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified

Respondido 23 Feb 16, 02:02

Solo un cambio de sintaxis de la antigua sintaxis de [myLabel sizeToFit]. ¡Gracias! - Velkoon

Esta es una solución antigua, use el diseño automático en iOS> = 6

Mi solución:

  1. Dividir líneas por mí mismo (ignorando la configuración de envoltura de etiquetas)
  2. Dibujar líneas por mí mismo (ignorando la alineación de la etiqueta)

@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

Respondido 11 Oct 19, 13:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.