Ajuste la altura de UILabel según el texto
-
22-07-2019 - |
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.
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,
Guía paso a paso: -
Paso 1: - Establezca la restricción en UIView
1) Liderando 2) Arriba 3) Trailing (Desde la vista principal)
Paso 2: - Establezca la restricción en la Etiqueta 1
1) Líder 2) Top 3) Trailing (desde su superview)
Paso 3: - Establezca la restricción en la Etiqueta 2
1) Líder 2) Trailing (desde su supervista)
Paso 4: - Más complicado dale un botton a UILabel desde UIView.
Paso 5: - (Opcional) Establezca la restricción en UIButton
1) Principal 2) Inferior 3) Final 4) Altura fija (desde la vista principal)
Salida: -
Nota: - asegúrese de haber establecido Número de líneas = 0 en la propiedad Etiqueta.
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 .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
-
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.
- Establecer restricción para UILabel. (En mi caso hice ancho superior, izquierdo y fijo)
- Establezca Número de línea en 0 en el Inspector de atributos
- Establezca Salto de línea en WordWrap en el Inspector de atributos.