Cambia el tamaño de UILabel para que encaje text dentro de UITableViewCell personalizado independientemente del ancho

Estoy intentando que una label en una celda sea del tamaño correcto, independientemente del dispositivo u orientación. Soy capaz de get la altura de la fila al tamaño correcto. También puedo configurar correctamente la altura de la label en cellForRowAtIndexPath , y puedo verificarla en mis loggings. Pero, en el momento en que llegue a willDisplayRowAtIndexPath , la altura de la label ha cambiado, pero solo cuando la celda no tiene 320 puntos de ancho.

Aquí está mi código

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"CustomCellIdentifier"; CustomInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil){ cell = [[CustomInfoCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@"CustomInfoCell" owner:self options:nil]; cell = objects[0]; } // Configure the cell... cell.customTitleLabel.text = [_data[indexPath.row] objectForKey:t]; CGFloat labelWidth = self.view.frame.size.width-40; NSLog(@"labelWidth:%f",labelWidth); NSString *text = [_data[indexPath.row] objectForKey:d];//correct text CGSize labelsize=[text sizeWithFont:cell.customDetailLabel.font constrainedToSize:CGSizeMake(labelWidth, 2000.0) lineBreakMode:cell.customDetailLabel.lineBreakMode]; NSLog(@"labelsize:%f,%f",labelsize.width,labelsize.height); //For testing cell.customDetailLabel.backgroundColor = [UIColor networkingColor]; NSLog(@"Pre: %@",cell.customDetailLabel); cell.customDetailLabel.frame=CGRectMake(20, 22, labelWidth, labelsize.height); cell.customDetailLabel.text = text; NSLog(@"Post: %@",cell.customDetailLabel); return cell; } 

En willDisplayRowAtIndexPath también willDisplayRowAtIndexPath la información de la label. Esto es lo que imprime una fila:

 2013-03-24 18:33:44.009 Bridge Alert[57793:1e503] labelWidth:728.000000 2013-03-24 18:33:44.010 Bridge Alert[57793:1e503] labelsize:713.000000,76.000000 2013-03-24 18:33:44.010 Bridge Alert[57793:1e503] Pre: <UILabel: 0xad3eaf0; frame = (20 20; 280 21); text = 'Detail'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 2013-03-24 18:33:44.011 Bridge Alert[57793:1e503] Post: <UILabel: 0xad3eaf0; frame = (20 22; 728 76); text = 'Detail'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 2013-03-24 18:33:44.011 Bridge Alert[57793:1e503] Text set: <UILabel: 0xad3eaf0; frame = (20 22; 728 76); text = 'A bridge is considenetworking “f...'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 2013-03-24 18:33:44.014 Bridge Alert[57793:1e503] Display:<UILabel: 0xad3eaf0; frame = (20 20; 728 190); text = 'A bridge is considenetworking “f...'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 

Como puede ver, en Pantalla, la label cambia de tamaño. Supongo que la altura se recalcula de alguna manera, en function de si la celda tenía 320 p. De ancho, que es el ancho UITableViewCell incorporado.

¿Cómo puedo hacer que la label se ajuste al tamaño correcto?

¿Has intentado desmarcar el layout automático? Esto eliminará las Restricciones innecesarias (en su mayoría poco útiles).

Esto es lo que funcionó para mí con el código mínimo posible usando AutoLayout .

Dentro de mi ViewController agregué los siguientes methods

 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString * yourText = //place here the text you want to calculate its size; return 40 + [self heightForText:yourText]; } -(CGFloat)heightForText:(NSString *)text { NSInteger MAX_HEIGHT = 2000; UITextView * textView = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 320, MAX_HEIGHT)]; textView.text = text; textView.font = [UIFont boldSystemFontOfSize:12]; [textView sizeToFit]; return textView.frame.size.height; } 

Este código anterior básicamente cambia el tamaño de UITableViewCell en function del tamaño de mi UILabel + un número de relleno que, en mi caso, definí como 40.

Después de esto, tuve que agregar un par de restricciones como se muestra a continuación para hacer que el UILabel se "estire" como lo hace UITableViewCell

introduzca la descripción de la imagen aquí

Después de ejecutarlo:

introduzca la descripción de la imagen aquí

Nota: Tomé diferentes piezas de código de muchos subprocesss en SO para llegar a esta solución. Ojalá pudiera recordar a todos 'para mencionar aquí

Espero que funcione para ustedes.

Aclamaciones

En mi opinión, el generador de interfaces / storyboard puede ser útil pero a menudo agrega otra capa innecesaria de complejidad. Simplemente subclass UITableViewCell (como es usted, pero hágalo puramente mediante progtwigción) y establezca el marco de customDetailLabel utilizando las presentaciones de layout.

Solía ​​tener el mismo problema, por alguna razón, la altura de la label cambia cuando realmente se muestra. Terminé usando el marco Sensible TableView gratuito, que realmente logra hacer el cambio de tamaño correctamente (incluso cambia el tamaño de la celda si elige tener una UILabel multilínea). El marco también le asignó automáticamente el text de la label a la propiedad de mi object, lo cual fue genial.

Intente anular setFrame en su class CustomInfoCell para include cambiar el tamaño de los elementos en su celda después de configurar el marco. He incluido el código que utilizo para lograr esto, que es un poco diferente de su implementación. Además, en su label, establezco la máscara de UIViewAutoresizingFlexibleWidth en UIViewAutoresizingFlexibleWidth .

Tenga esto en la parte superior de su file:

 static void *kKVOContext; // See: http://www.dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage/ 

En viewDidLoad incluye:

 [self.textLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:&kKVOContext]; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]]; 

Luego incluya:

 - (void)setFrame:(CGRect)frame { [super setFrame:frame]; //Resize elements to fit inside new frame [self textChanged]; } - (CGSize)textLabelSize { BOOL portrait = UIInterfaceOrientationIsPortrait([UIApplication shanetworkingApplication].statusBarOrientation); CGFloat width = portrait ? [UIScreen mainScreen].bounds.size.width : [UIScreen mainScreen].bounds.size.height; CGFloat maxWidth = width - 90 - TEXT_X_LEFT_PADDING; CGSize maximumLabelSize = CGSizeMake(maxWidth, 10000); return [self.textLabel.text sizeWithFont:self.textLabel.font constrainedToSize:maximumLabelSize lineBreakMode:self.textLabel.lineBreakMode]; } - (CGFloat)cellHeight { CGSize expectedLabelSize = [self textLabelSize]; return (self.titleLabel.frame.origin.y+self.titleLabel.frame.size.height) + expectedLabelSize.height; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqual:@"text"] && object == self.textLabel) { [self textChanged]; } if(context != &kKVOContext) { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (void)orientationChanged:(NSNotification *)note { //Resize text on orientation change [self textChanged]; } - (void)textChanged { CGRect newFrame = self.textLabel.frame; newFrame.size = [self textLabelSize]; if(!CGRectEqualToRect(self.textLabel.frame, newFrame)) { self.textLabel.frame = newFrame; } } 

Solo publico mi propio enfoque simplificado basado en @Paulo, pero ahora con adaptarme al ancho de las restricciones de storyboard y más preciso.

(Rápido)

 override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier")! // Use subclass of UITableViewCell if your cell is complex. let label = cell.viewWithTag(3001) as! UILabel; label.text = someStringArray[indexPath.row] label.sizeToFit(); let y = label.frame.origin.y let height = label.frame.size.height let paddingBottom: CGFloat = 8 // add other controls/view height if any after the expand label return y + height + paddingBottom }