2011-08-19 15 views
9

Sono nuovo allo sviluppo di iOS e questo è il mio problema fino ad ora. Sono in grado di calcolare in modo dinamico l'altezza di una cella personalizzata tramite il delegato "heightForRowAtIndexPath". Quindi, al primo carico, ogni cosa viene visualizzata perfettamente bene.IOS: altezza dinamica con uitableviewcell personalizzata

Il mio problema è che non appena inizio lo scorrimento, tutto fa solo casino. Penso che mentre si scorre "heightForRowAtIndexPath" non viene più chiamato per cella che viene visualizzato sullo schermo, quindi la nuova altezza della cella non può essere calcolata.

Quindi sono rimasto bloccato qui per un po '. Mi stavo chiedendo se qualcuno di voi potesse prestarmi una mano. Grazie in anticipo.

Inserirò il codice in file pertinenti. Questi file includono il file h e m della cella personalizzata. e funzioni pertinenti del file m del controller di visualizzazione.

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

risposta

4

Se il testo nelle celle sta per cambiare, si avrà bisogno di una chiamata reloadData sul tableView quando lo fa, altrimenti il ​​tableView: heightForRowAtIndexPath: non verrà chiamato.

Il modo in cui tabellaView funziona è che raccoglie le altezze per tutte le righe ad ogni ricarica (e le varianti di ricarica). Questo è il modo in cui iOS conosce l'altezza dell'intera tabella. Non chiama tableView: heightForRowAtIndexPath: di nuovo quando si afferrano le singole celle. Di solito chiamare reloadData è abbastanza veloce e questo metodo, a differenza delle sue varianti, non causa alcun scorrimento.

Vedere stackoverflow question and answer per sfondo utile.

I problemi si presentano se devi fare molto lavoro per calcolare altezze e hai centinaia o migliaia di file. In un caso d'uso mi piace così, memorizzo i calcoli dell'altezza delle righe per ottenere prestazioni decenti. Ma se questo non è il tuo caso, sii un po 'più liberale con reloadData.

1

tuo tableView:heightForRowAtIndexPath: sembra corretto, ma si potrebbe desiderare di controllare quanto segue circa l'etichetta della cella labelDescription nel file XIB:

  • deve corrispondere alla larghezza utilizzata nel metodo tableView:heightForRowAtIndexPath: (nel tuo caso, 320)
  • deve corrispondere il tipo di carattere e le dimensioni utilizzato nel metodo tableView:heightForRowAtIndexPath: (nel tuo caso "Arial" size 15)
  • impostato dell'etichetta "Adjust per adattarsi" casella di controllo per NO
  • impostare la # dei beni linee a 0 (chemodo si permette al testo di più righe)

Se si sospetta che il metodo tableView:heightForRowAtIndexPath: non viene chiamato dopo lo scorrimento, si può facilmente verificare che l'aggiunta di una dichiarazione NSLog temporanea in quel metodo. Se non viene mai chiamato, è possibile che tu abbia dimenticato di impostare il controller di visualizzazione come delegato UITableViewDelegate di UITableView.

Problemi correlati