2011-08-19 30 views
9

Soy nuevo en el desarrollo de ios y este es mi problema hasta el momento. Puedo calcular dinámicamente la altura de una celda personalizada a través del delegado "heightForRowAtIndexPath". Entonces, en la primera carga, todo se muestra perfectamente bien.IOS: altura dinámica con una uitableviewcell personalizada

Mi problema es que tan pronto como empiezo a desplazarme, todo simplemente se estropea. Creo que mientras se desplaza el "heightForRowAtIndexPath" ya no se llama por celda que aparece en la pantalla, por lo que no se puede calcular la nueva altura de la celda.

Así que estuve estancado aquí por un tiempo. Me preguntaba si alguno de ustedes podría echarme una mano. gracias de antemano.

Voy a publicar el código en los archivos correspondientes. Estos archivos incluyen el archivo personalizado h y m de la celda. y funciones relevantes del controlador de vista m archivo.

// ###################################################### 
// HelpTableViewCell.h 
#import <UIKit/UIKit.h> 

@interface HelpTableViewCell : UITableViewCell { 
    IBOutlet UILabel *labelName; 
    IBOutlet UILabel *labelDescription; 

    IBOutlet UIView *viewBackground; 
} 

@property (nonatomic, retain) UILabel *labelName; 
@property (nonatomic, retain) UILabel *labelDescription; 

@property (nonatomic, retain) UIView *viewBackground; 

@end 

// ###################################################### 
// HelpTableViewCell.m 
#import "HelpTableViewCell.h" 

@implementation HelpTableViewCell 

@synthesize labelName; 
@synthesize labelDescription; 

@synthesize viewBackground; 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 

    if (self) { 
    } 

    return self; 
} 

- (void)setSelected:(BOOL)selected animated:(BOOL)animated { 

    self.labelName.lineBreakMode = UILineBreakModeWordWrap; 
    self.labelName.numberOfLines = 0; 
    self.labelName.font = [UIFont boldSystemFontOfSize:15]; 
    [self.labelName sizeToFit]; 

    self.labelDescription.lineBreakMode = UILineBreakModeWordWrap; 
    self.labelDescription.numberOfLines = 0; 
    self.labelDescription.font = [UIFont fontWithName:@"Arial" size:15]; 
    [self.labelDescription sizeToFit]; 

    [super setSelected:selected animated:animated]; 
} 

- (void) dealloc { 
    [labelName release], labelName = nil; 
    [labelDescription release], labelDescription = nil; 

    [super dealloc]; 
} 

@end 


// ###################################################### 
// in my view controller m file 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellIdentifier = @"HelpTableViewCell"; 
    HelpTableViewCell *cell = (HelpTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    if (cell == nil) { 
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"HelpTableViewCell" owner:nil options:nil]; 

    for (id currentObject in topLevelObjects) { 
     if ([currentObject isKindOfClass:[UITableViewCell class]]) { 
     cell = (HelpTableViewCell *) currentObject; 
     break; 
     } 
    } 

    } 

    cell.labelName.text = [self.instructionName objectAtIndex:indexPath.row]; 
    cell.labelDescription.text = [self.instructionDescription objectAtIndex:indexPath.row]; 

    return cell; 
} 

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSString *cellText = [self.instructionDescription objectAtIndex:indexPath.row]; 
    UIFont *cellFont = [UIFont fontWithName:@"Arial" size:15]; 
    CGSize constraintSize = CGSizeMake(320.0f, MAXFLOAT); 
    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap]; 

    return labelSize.height + 25; 
} 

Respuesta

4

Si el texto de las celdas va a cambiar, que se necesitan para una llamada reloadData en su tableView cuando lo hace, de lo contrario el tableView: heightForRowAtIndexPath: no se llamará.

La manera en que funciona tableView es que reúne las alturas para todas las filas en cada recarga (y las variantes de recarga). Así es como iOS conoce la altura de toda la tabla. No llama a tableView: heightForRowAtIndexPath: de nuevo al tomar celdas individuales. Por lo general, llamar a reloadData es bastante rápido y este método, a diferencia de sus variantes, no causa ningún desplazamiento.

Ver stackoverflow question and answer para antecedentes útiles.

Los problemas surgen si tiene que trabajar mucho para calcular las alturas y tiene cientos o miles de filas. En un caso de uso que tengo así, guardo en caché los cálculos de altura de fila para obtener un rendimiento decente. Pero si ese no es tu caso, solo sé un poco más liberal con reloadData.

1

Su tableView:heightForRowAtIndexPath: parece correcta, pero es posible que desee comprobar lo siguiente acerca de la etiqueta de células labelDescription en su archivo XI ter:

  • debe coincidir con el ancho utilizado en el método tableView:heightForRowAtIndexPath: (en su caso, 320)
  • debe coincidir con el tipo de letra y tamaño usado en el método tableView:heightForRowAtIndexPath: (en su caso "Arial" size 15)
  • fija de la etiqueta "Ajuste a su" casilla de verificación en NO
  • establecer el # de la propiedad líneas a 0 (que forma en que se permite que el texto para abarcar varias líneas)

Si sospecha que el método tableView:heightForRowAtIndexPath: no consigue llamó después se desplaza, puede verificar fácilmente que mediante la adición de una declaración NSLog temporal en ese método. Si nunca se llama, es posible que haya olvidado configurar su controlador de vista como el delegado UITableView de UITableViewDelegate.

Cuestiones relacionadas