Ajuste la altura de UILabel según el texto

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

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, stackres, automóviles, escombros y otros objetos.

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

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

Por favor, avíseme si no voy en la dirección correcta. Gracias.

sizeWithFont constrainedToSize:lineBreakMode: es el método a usar. Un ejemplo de cómo usarlo está a continuación:

 //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; 

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 dynamic de tags: preferredMaxLayoutWidth .

El uso de esta propiedad en combinación con lineBreakMode = NSLineBreakByWordWrapping y el método sizeToFit permite cambiar 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 programáticamente, puede hacer esto en Storyboard / XIB durante el diseño.

  • Establezca la propiedad Número de líneas de UIlabel en 0 en el inspector de atributos.
  • A continuación, establezca la restricción de ancho / (o) restricción inicial y final según el requisito.
  • A continuación, establezca la restricción de altura con el valor mínimo . Finalmente, seleccione la restricción de altura que ha agregado y en el inspector de tamaño la que está junto al inspector de atributos, cambie la relación de la restricción de altura de igual amayor que .

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

Hice una demostración para usted según su requisito. Descárguelo desde el siguiente enlace,

Autoresize UIView y UILabel

Guía paso por paso :-

Paso 1: – Establecer la restricción a UIView

1) Líder 2) Superior 3) Seguimiento (desde la vista principal)

enter image description here

Paso 2: establece la restricción en la etiqueta 1

1) Liderando 2) Top 3) A la cola (desde su superview)

enter image description here

Paso 3: establece la restricción en la etiqueta 2

1) Leading 2) Trailing (De su superview)

enter image description here

Paso 4: – Lo más complicado es dar botton a UILabel desde UIView.

enter image description here

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

1) Líder 2) Parte inferior 3) Trailing 4) Altura fija (Desde la vista principal)

enter image description here

Salida: –

enter image description here

Nota: – Asegúrese de haber configurado Número de líneas = 0 en la propiedad Etiqueta.

enter image description here

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

Gracias chicos por la ayuda, aquí está el código que probé, que funciona para mí

  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  #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 

Como sizeWithFont está en desuso, yo uso este en su lugar.

éste 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 TableViewController's (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; 

También use el NSString sizeWithFont:constrainedToSize: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 funcionó para mí fue aplicar restricción de altura a la etiqueta y establecer la prioridad a bajo , es decir, (250) en el guión gráfico.

Por lo tanto, no tiene que preocuparse por calcular la altura y el ancho de forma programática, gracias al guión gráfico.

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. Me di cuenta de que cuando uso:

 [cell.contentView addSubview:cellLabel]; 

en tableView: cellForRowAtIndexPath: método en el que la vista de etiqueta se representaba continuamente sobre la parte superior de la vista anterior cada vez que editaba la celda. El texto se pixelado, y cuando se borró o modificó algo, la versión anterior fue visible en 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ázmelo 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ébela aumentando el texto en el elementoTitle.text como

 itemTitle.text = @"diofgorigjveghnhkvjteinughntivugenvitugnvkejrfgnvkhv"; 

mostrará la respuesta de perfetc como necesites

Puede usarlo como un método, también. @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úralo 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 establecer un frame.size.height en el float máximo, esto dará lugar para el texto largo, pero sizeToFit() lo forzará a usar solo el necesario, pero SIEMPRE lo llamará después de configurar el .frame.size.height .

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

Para hacer esto en Swift3 a continuación está 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 con .height obtendrá la altura de la etiqueta de la siguiente manera:

 neededSize.height 

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

 newFrame.size.height = maximumLabelSize.height; 

debiera 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í, soy tonto), estaba redimensionando la etiqueta al valor predeterminado en el método cellForRowAtIndexPath – estaba pasando por alto el código que había escrito antes:

 - (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 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 UILable en el guión gráfico, incluida la esquina superior izquierda inferior derecha

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 } 

Agregando a las respuestas anteriores:

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

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

Ajuste de altura UILabel

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() 

El problema es que ninguna de las funciones mencionadas es realiable y para algunas cadenas y fonts devolverán un valor de altura incorrecto. Especialmente fallará para los textos atribuidos.

La única solución confiable es aquí: https://stackoverflow.com/a/4214978/699944 y el punto es utilizar CoreText para calcular manualmente la altura de cada línea para obtener el tamaño correcto. No hay otra forma conocida de hacer esto.