Pregunta

Considere que tengo el siguiente texto en un UILabel (una larga línea de texto dinámico):

  

Dado que el ejército alienígena supera ampliamente al equipo, los jugadores deben usar el mundo post-apocalíptico para su ventaja, como buscar refugio detrás de contenedores de basura, pilares, autos, escombros y otros objetos.

Quiero cambiar el tamaño de la altura de UILabel para que el texto pueda caber. Estoy usando las siguientes propiedades de UILabel para hacer que el texto se ajuste.

myUILabel.lineBreakMode = UILineBreakModeWordWrap;
myUILabel.numberOfLines = 0;

Avíseme si no me dirijo en la dirección correcta. Gracias.

¿Fue útil?

Solución

sizeWithFont restrictinedToSize: lineBreakMode: es el método a utilizar. A continuación se muestra un ejemplo de cómo usarlo:

//Calculate the expected size based on the font and linebreak mode of your label
// FLT_MAX here simply means no constraint in height
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);

CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];   

//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;

Otros consejos

Ibas en la dirección correcta. Todo lo que necesitas hacer es:

myUILabel.numberOfLines = 0;
myUILabel.text = @"Enter large amount of text here";
[myUILabel sizeToFit];

En iOS 6, Apple ha agregado una propiedad a UILabel que simplifica enormemente el redimensionamiento vertical dinámico de las etiquetas: preferredMaxLayoutWidth .

El uso de esta propiedad en combinación con lineBreakMode = NSLineBreakByWordWrapping y el método sizeToFit permite cambiar fácilmente el tamaño de una instancia de UILabel a la altura que acomoda todo el texto.

Una cita de la documentación de iOS:

preferredMaxLayoutWidth El ancho máximo preferido (en puntos) para una etiqueta multilínea.

Discusión Esta propiedad afecta el tamaño de la etiqueta cuando se le aplican restricciones de diseño. Durante el diseño, si el texto se extiende más allá del ancho especificado por esta propiedad, el texto adicional fluye a una o más líneas nuevas, lo que aumenta la altura de la etiqueta.

Una muestra:

...
UILabel *status = [[UILabel alloc] init];
status.lineBreakMode = NSLineBreakByWordWrapping;
status.numberOfLines = 5; // limits to 5 lines; use 0 for unlimited.

[self addSubview:status]; // self here is the parent view

status.preferredMaxLayoutWidth = self.frame.size.width; // assumes the parent view has its frame already set.

status.text = @"Some quite lengthy message may go here…";
[status sizeToFit];
[status setNeedsDisplay];
...

En lugar de hacer esto mediante programación, puede hacerlo en Storyboard / XIB mientras diseña.

  • Establezca la propiedad número de líneas de UIlabel en 0 en el inspector de atributos.
  • Luego establezca la restricción de ancho / (o) restricción inicial y final según el requisito.
  • Luego, establezca la restricción de altura con valor mínimo . Finalmente, seleccione la restricción de altura que agregó y en el inspector de tamaño que está al lado del inspector de atributos, cambie la relación de la restricción de altura de igual a - < strong> mayor que .

Verifique este trabajo perfectamente sin agregar una sola línea de código. (Usando Autolayout)

Hice una demostración para usted de acuerdo con sus requisitos. Descárguelo del siguiente enlace,

Autoresize UIView y UILabel

Guía paso a paso: -

Paso 1: - Establezca la restricción en UIView

1) Liderando 2) Arriba 3) Trailing (Desde la vista principal)

 ingrese la descripción de la imagen aquí

Paso 2: - Establezca la restricción en la Etiqueta 1

1) Líder 2) Top 3) Trailing (desde su superview)

 ingrese la descripción de la imagen aquí

Paso 3: - Establezca la restricción en la Etiqueta 2

1) Líder 2) Trailing (desde su supervista)

 ingrese la descripción de la imagen aquí

Paso 4: - Más complicado dale un botton a UILabel desde UIView.

 ingrese la descripción de la imagen aquí

Paso 5: - (Opcional) Establezca la restricción en UIButton

1) Principal 2) Inferior 3) Final 4) Altura fija (desde la vista principal)

 ingrese la descripción de la imagen aquí

Salida: -

 ingrese la descripción de la imagen aquí

Nota: - asegúrese de haber establecido Número de líneas = 0 en la propiedad Etiqueta.

 ingrese la descripción de la imagen aquí

Espero que esta información sea suficiente para comprender Autoresize UIView según la altura de UILabel y Autoresize UILabel Según el texto.

Gracias a todos por su ayuda, aquí está el código que probé que me funciona

   UILabel *instructions = [[UILabel alloc]initWithFrame:CGRectMake(10, 225, 300, 180)];
   NSString *text = @"First take clear picture and then try to zoom in to fit the ";
   instructions.text = text;
   instructions.textAlignment = UITextAlignmentCenter;
   instructions.lineBreakMode = NSLineBreakByWordWrapping;
   [instructions setTextColor:[UIColor grayColor]];

   CGSize expectedLabelSize = [text sizeWithFont:instructions.font 
                                constrainedToSize:instructions.frame.size
                                    lineBreakMode:UILineBreakModeWordWrap];

    CGRect newFrame = instructions.frame;
    newFrame.size.height = expectedLabelSize.height;
    instructions.frame = newFrame;
    instructions.numberOfLines = 0;
    [instructions sizeToFit];
    [self addSubview:instructions];

Solución para iOS7 anterior y iOS7 anterior

//
//  UILabel+DynamicHeight.m
//  For StackOverFlow
//
//  Created by Vijay on 24/02/14.
//  Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//

#import <UIKit/UIKit.h>

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

#define iOS7_0 @"7.0"

@interface UILabel (DynamicHeight)

/*====================================================================*/

/* Calculate the size,bounds,frame of the Multi line Label */

/*====================================================================*/
/**
 *  Returns the size of the Label
 *
 *  @param aLabel To be used to calculte the height
 *
 *  @return size of the Label
 */

-(CGSize)sizeOfMultiLineLabel;

@end


//
//  UILabel+DynamicHeight.m
//  For StackOverFlow
//
//  Created by Vijay on 24/02/14.
//  Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//

#import "UILabel+DynamicHeight.h"

@implementation UILabel (DynamicHeight)
/*====================================================================*/

/* Calculate the size,bounds,frame of the Multi line Label */

/*====================================================================*/
/**
 *  Returns the size of the Label
 *
 *  @param aLabel To be used to calculte the height
 *
 *  @return size of the Label
 */
-(CGSize)sizeOfMultiLineLabel{

    NSAssert(self, @"UILabel was nil");

    //Label text
    NSString *aLabelTextString = [self text];

    //Label font
    UIFont *aLabelFont = [self font];

    //Width of the Label
    CGFloat aLabelSizeWidth = self.frame.size.width;


    if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
        //version < 7.0

        return [aLabelTextString sizeWithFont:aLabelFont
                            constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                lineBreakMode:NSLineBreakByWordWrapping];
    }
    else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
        //version >= 7.0

        //Return the calculated size of the Label
        return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                              options:NSStringDrawingUsesLineFragmentOrigin
                                           attributes:@{
                                                        NSFontAttributeName : aLabelFont
                                                        }
                                              context:nil].size;

    }

    return [self bounds].size;

}

@end

Dado que sizeWithFont está en desuso, uso este en su lugar.

este obtiene atributos específicos de etiqueta.

-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text{

    NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:label.font}];
    CGRect rect = [attributedText boundingRectWithSize:(CGSize){label.frame.size.width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];

    return ceil(rect.size.height);
}

Aquí hay una versión de categoría:

UILabel + AutoSize.h     #import

@interface UILabel (AutoSize)

- (void) autosizeForWidth: (int) width;

@end

UILabel+AutoSize.m

#import "UILabel+AutoSize.h"

@implementation UILabel (AutoSize)

- (void) autosizeForWidth: (int) width {
    self.lineBreakMode = UILineBreakModeWordWrap;
    self.numberOfLines = 0;
    CGSize maximumLabelSize = CGSizeMake(width, FLT_MAX);
    CGSize expectedLabelSize = [self.text sizeWithFont:self.font constrainedToSize:maximumLabelSize lineBreakMode:self.lineBreakMode];
    CGRect newFrame = self.frame;
    newFrame.size.height = expectedLabelSize.height;
    self.frame = newFrame;
}

@end

Puede implementar el método TableViewController (UITableViewCell *) tableView: cellForRowAtIndexPath de la siguiente manera (por ejemplo):

#define CELL_LABEL_TAG 1

- (UITableViewCell *)tableView:(UITableView *)tableView  cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *text = @"my long text";

    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero  reuseIdentifier:identifier] autorelease];
    }

    CGFloat width = [UIScreen mainScreen].bounds.size.width - 50;
    CGFloat height = [self textHeight:text] + 10;
    CGRect frame = CGRectMake(10.0f, 10.0f, width, height);

    UILabel *cellLabel = [[UILabel alloc] initWithFrame:frame];
    cellLabel.tag = CELL_LABEL_TAG;
    cellLabel.textColor = [UIColor blackColor];
    cellLabel.backgroundColor = [UIColor clearColor];
    cellLabel.textAlignment = UITextAlignmentLeft;
    cellLabel.font = [UIFont systemFontOfSize:12.0f];
    [cell.contentView addSubview:cellLabel];
    [cellLabel release];

    return cell;
}

UILabel *label = (UILabel *)[cell viewWithTag:CELL_LABEL_TAG];
label.text = text;
label.numberOfLines = 0;
[label sizeToFit];
return cell;

Utilice también el método NSString de sizeWithFont: restrictinedToSize: lineBreakMode: para calcular la altura del texto.

Y para aquellos que están migrando a iOS 8, aquí hay una extensión de clase para Swift:

extension UILabel {

    func autoresize() {
        if let textNSString: NSString = self.text {
            let rect = textNSString.boundingRectWithSize(CGSizeMake(self.frame.size.width, CGFloat.max),
                options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                attributes: [NSFontAttributeName: self.font],
                context: nil)
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, rect.height)
        }
    }

}

La forma más fácil y mejor que me funcionó fue aplicar la restricción de altura a la etiqueta y establecer la prioridad en baja , es decir, (250) en el guión gráfico.

Por lo tanto, no debe preocuparse por calcular la altura y el ancho mediante programación, gracias al guión gráfico.

Extensión UILabel basada en esta respuesta para Swift 4 y superior

extension UILabel {

    func retrieveTextHeight () -> CGFloat {
        let attributedText = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName:self.font])

        let rect = attributedText.boundingRect(with: CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)

        return ceil(rect.size.height)
    }

}

Se puede usar como:

self.labelHeightConstraint.constant = self.label.retrieveTextHeight()

Método actualizado

+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {

    CGSize constraint = CGSizeMake(width, 20000.0f);
    CGSize size;

    CGSize boundingBox = [text boundingRectWithSize:constraint
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:@{NSFontAttributeName:font}
                                                  context:nil].size;

    size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));

    return size.height;
}

Gracias por esta publicación. Me ayudó mucho. En mi caso, también estoy editando el texto en un controlador de vista separado. Noté que cuando uso:

[cell.contentView addSubview:cellLabel];

en tableView: cellForRowAtIndexPath: método por el que la vista de etiqueta se renderizó continuamente sobre la parte superior de la vista anterior cada vez que edité la celda. El texto se pixeló, y cuando algo se eliminó o cambió, la versión anterior era visible bajo la nueva versión. Así es como resolví el problema:

if ([[cell.contentView subviews] count] > 0) {
    UIView *test = [[cell.contentView subviews] objectAtIndex:0];
    [test removeFromSuperview];
}
[cell.contentView insertSubview:cellLabel atIndex:0];

No más capas extrañas. Si hay una mejor manera de manejar esto, hágamelo saber.

UILabel *itemTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10,100, 200.0f)];
itemTitle.text = @"aseruy56uiytitfesh";
itemTitle.adjustsFontSizeToFitWidth = NO;
itemTitle.autoresizingMask = UIViewAutoresizingFlexibleWidth;
itemTitle.font = [UIFont boldSystemFontOfSize:18.0];
itemTitle.textColor = [UIColor blackColor];
itemTitle.shadowColor = [UIColor whiteColor];
itemTitle.shadowOffset = CGSizeMake(0, 1);
itemTitle.backgroundColor = [UIColor blueColor];
itemTitle.lineBreakMode = UILineBreakModeWordWrap;
itemTitle.numberOfLines = 0;
[itemTitle sizeToFit];
[self.view addSubview:itemTitle];

use esto aquí, todas las propiedades se usan en la etiqueta y pruébelo incrementando el texto en el elemento Título como

itemTitle.text = @"diofgorigjveghnhkvjteinughntivugenvitugnvkejrfgnvkhv";

mostrará la respuesta perfecta según lo necesite

También puede usarlo como método. @Pyjamasam es muy cierto, así que solo estoy haciendo su método. Puede ser útil para alguien más

-(CGRect)setDynamicHeightForLabel:(UILabel*)_lbl andMaxWidth:(float)_width{
    CGSize maximumLabelSize = CGSizeMake(_width, FLT_MAX);

    CGSize expectedLabelSize = [_lbl.text sizeWithFont:_lbl.font constrainedToSize:maximumLabelSize lineBreakMode:_lbl.lineBreakMode];

    //adjust the label the the new height.
    CGRect newFrame = _lbl.frame;
    newFrame.size.height = expectedLabelSize.height;
    return newFrame;
}

y simplemente configúrelo así

label.frame = [self setDynamicHeightForLabel:label andMaxWidth:300.0];

Swift 2:

    yourLabel.text = "your very long text"
    yourLabel.numberOfLines = 0
    yourLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
    yourLabel.frame.size.width = 200
    yourLabel.frame.size.height = CGFloat(MAXFLOAT)
    yourLabel.sizeToFit()

Las líneas interesantes son sizeToFit () junto con la configuración de un frame.size.height al máximo flotante, esto dará espacio para texto largo, pero sizeToFit () lo obligará a usar solo lo necesario, pero SIEMPRE lo llamará después de configurar .frame.size.height .

Recomiendo configurar un .backgroundColor para fines de depuración, de esta manera puede ver el marco que se representa para cada caso.

Para hacer esto en Swift3 lo siguiente es el código:

 let labelSizeWithFixedWith = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
            let exactLabelsize = self.label.sizeThatFits(labelSizeWithFixedWith)
            self.label.frame = CGRect(origin: CGPoint(x: 20, y: 20), size: exactLabelsize)

Esta es una línea de código para obtener la Altura UILabel usando Objective-c:

labelObj.numberOfLines = 0;
CGSize neededSize = [labelObj sizeThatFits:CGSizeMake(screenWidth, CGFLOAT_MAX)];

y usando .height obtendrá el alto de la etiqueta de la siguiente manera:

neededSize.height

Mi enfoque para calcular la altura dinámica de UILabel.

    let width = ... //< width of this label 
    let text = ... //< display content

    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.preferredMaxLayoutWidth = width

    // Font of this label.
    //label.font = UIFont.systemFont(ofSize: 17.0)
    // Compute intrinsicContentSize based on font, and preferredMaxLayoutWidth
    label.invalidateIntrinsicContentSize() 
    // Destination height
    let height = label.intrinsicContentSize.height

Ajustar a la función:

func computeHeight(text: String, width: CGFloat) -> CGFloat {
    // A dummy label in order to compute dynamic height.
    let label = UILabel()

    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.font = UIFont.systemFont(ofSize: 17.0)

    label.preferredMaxLayoutWidth = width
    label.text = text
    label.invalidateIntrinsicContentSize()

    let height = label.intrinsicContentSize.height
    return height
}

Puede obtener la altura usando el código a continuación

Tienes que pasar

  1. texto 2. fuente 3. ancho de etiqueta

    func heightForLabel(text: String, font: UIFont, width: CGFloat) -> CGFloat {
    
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()
    
    return label.frame.height
    }
    

Una línea es que la respuesta de Chris es incorrecta.

newFrame.size.height = maximumLabelSize.height;

debería ser

newFrame.size.height = expectedLabelSize.height;

Aparte de eso, es la solución correcta.

Finalmente, funcionó. Gracias chicos.

No lo estaba haciendo funcionar porque estaba tratando de cambiar el tamaño de la etiqueta en el método heightForRowAtIndexPath :

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

y (sí, tonto), estaba cambiando el tamaño de la etiqueta a la predeterminada en el método cellForRowAtIndexPath : estaba pasando por alto el código que había escrito anteriormente:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    cellIdentifier = @"myCell";
    cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    cell.myUILabel.lineBreakMode = UILineBreakModeWordWrap;        
    cell.myUILabel.numberOfLines = 0;
    cell.myUILabel.text = @"Some very very very very long text....."
    [cell.myUILabel.criterionDescriptionLabel sizeToFit];    
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    CGFloat rowHeight = cell.myUILabel.frame.size.height + 10;

    return rowHeight;    
}
NSString *str = @"Please enter your text......";
CGSize lblSize = [str sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize: CGSizeMake(200.0f, 600.0f) lineBreakMode: NSLineBreakByWordWrapping];

UILabel *label = [[UILabel alloc]init];
label.frame = CGRectMake(60, 20, 200, lblSize.height);
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.font = [UIFont systemFontOfSize:15];
label.text = str;
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
[self.view addSubview:label];

Mi código:

UILabel *label      = [[UILabel alloc] init];
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.text          = text;
label.textAlignment = NSTextAlignmentCenter;
label.font          = [UIFont fontWithName:_bodyTextFontFamily size:_bodyFontSize];

CGSize size = [label sizeThatFits:CGSizeMake(width, MAXFLOAT)];


float height        = size.height;
label.frame         = CGRectMake(x, y, width, height);

Este método le dará una altura perfecta

-(float) getHeightForText:(NSString*) text withFont:(UIFont*) font andWidth:(float) width{
CGSize constraint = CGSizeMake(width , 20000.0f);
CGSize title_size;
float totalHeight;


title_size = [text boundingRectWithSize:constraint
                                options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{ NSFontAttributeName : font }
                                context:nil].size;

totalHeight = ceil(title_size.height);

CGFloat height = MAX(totalHeight, 40.0f);
return height;
}
myLabel.text = "your very long text"
myLabel.numberOfLines = 0
myLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping

Establezca restricciones para UILabel en el guión gráfico, incluida la parte superior izquierda inferior derecha

Agregando a las respuestas anteriores:

Esto se puede lograr fácilmente a través del guión gráfico.

  1. Establecer restricción para UILabel. (En mi caso hice ancho superior, izquierdo y fijo)
  2. Establezca Número de línea en 0 en el Inspector de atributos
  3. Establezca Salto de línea en WordWrap en el Inspector de atributos.

 Ajuste de altura de UILabel

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top