2009-12-22 13 views
22

Sto costruendo una visualizzazione delle impostazioni in-applicazione personalizzata basata su UITableViewCellStyle1 (o così).calcolo dinamico della larghezza UILabel in UITableViewCell

Sto provando a calcolare in modo dinamico la larghezza dell'etichetta sinistra (titolo) di una cella per determinare quanto può essere ampio il campo di testo a destra.

Quando avvio l'app nel simulatore e la vista viene caricata, la larghezza delle etichette del titolo è zero fino a quando non scorro la vista e una cella non è visibile, quindi quando si scorre indietro la dimensione si regola come previsto. Credo che questo potrebbe dover fare qualcosa con il riutilizzo delle cellule.

Ho bisogno che le etichette del titolo nelle celle abbiano la loro larghezza corretta quando la vista viene caricata, non dopo che sono scomparse una sola volta.

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath 
    { 
     static NSString* reuseIdentifier = @"SettingsCell"; 

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; 

if (!cell) 
{ 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier] autorelease]; 
    [cell setBackgroundColor:[UIColor baeDarkGrayColor]]; 


    UILabel* cellLabel = [cell textLabel]; 
    [cellLabel setTextColor:[UIColor whiteColor]]; 
    [cellLabel setBackgroundColor:[UIColor clearColor]]; 

    [cell setUserInteractionEnabled:YES]; 
    [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; 
} 

// Populate cell with corresponding data. 
NSDictionary* tableSection = [_tableData objectAtIndex:indexPath.section]; 

// Set the label 
UILabel* textLabel = [cell textLabel]; 
NSString* labelString = [[tableSection objectForKey:@"itemTitles"] objectAtIndex:indexPath.row]; 
[textLabel setText:labelString]; 

    // CGSize constrainedSize; 
    // constrainedSize.width = MAXFLOAT; 
// constrainedSize.height = MAXFLOAT; 

CGSize textLabelSize = [textLabel.text sizeWithFont:textLabel.font /*constrainedToSize:constrainedSize*/]; 

NSLog(@"text label width: %f", textLabelSize.width);  


// Set the accessory view 
BAESettingsTableCellAccessoryType accessoryType = [[[tableSection objectForKey:@"itemAccessories"] objectAtIndex:indexPath.row] integerValue]; 
switch (accessoryType) 
{ 
    case BAESettingsTableCellAccessoryDisclosureIndicator: 
    { 
     UIImageView* disclosureView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"AccessoryDisclosure.png"]]; 
     [cell setAccessoryView:disclosureView]; 
     [disclosureView release]; 
     break; 
    } 
    case BAESettingsTableCellAccessoryOnOffSwitch: 
    { 
     UISwitch* onOffSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; 
     [onOffSwitch setOn:YES]; 
     [cell setAccessoryView:onOffSwitch]; 
     [onOffSwitch release]; 
     break; 
    } 
    case BAESettingsTableCellAccessoryNone: 
     // default: 
     // break; 
    { 

     CGRect cellFrame = [cell frame]; 

     float detailTextFieldWidth = cellFrame.size.width - (textLabelSize.width + 50); 
     float detailTextFieldHeight = cellFrame.size.height - 1; 

     NSLog(@"detail text field calculated frame width, height, %f, %f", detailTextFieldWidth, detailTextFieldHeight); 


     CGRect frame = CGRectMake(cellFrame.origin.x, cellFrame.origin.y, detailTextFieldWidth, detailTextFieldHeight); 


     UITextField* textField = [[UITextField alloc] initWithFrame:frame]; 
     NSString* detailLabelString = [[tableSection objectForKey:@"itemDetailStrings"] objectAtIndex:indexPath.row]; 
     textField.text = detailLabelString; 
     textField.textColor = cell.detailTextLabel.textColor; 
     textField.textAlignment = UITextAlignmentRight; 
     textField.borderStyle = UITextBorderStyleRoundedRect; 
     [cell setAccessoryView:textField]; 
     [textField release]; 
     break; 
    } 

} 

return cell; 
    } 

risposta

16

L'impostazione esplicita del carattere risolve il problema.

CGSize textLabelSize = [textLabel.text sizeWithFont:[UIFont systemFontOfSize:17]]; 

Gory detals:
Quando la Tableview primi carichi, questo frammento ritorna larghezza pari a zero a causa della dimensione del carattere essendo 0.

[textLabel.text sizeWithFont:textLabel.font] 

ho capito questo, visualizzando la dimensione in punti di il carattere della cella.

dimensioni
NSLog(@"font size: %f", cell.textLabel.font.pointSize); 

Il punto era pari a zero fino a quando il cellulare è andato fuori dallo schermo ed è tornato, proprio come hai descritto.

3

Ho trovato lo stesso problema, ma ho trovato una soluzione alternativa. FYI Ho sollevato un bug con Apple (ID bug 7535066). Lex, nel tuo esempio, se usi cell.font invece di textLabel.font, dovrebbe funzionare, anche se riceverai un avvertimento sul compilatore, poiché si tratta di una chiamata di metodo deprecata. Non sono sicuro se riuscirai a visualizzare i dettagli del bug che ho generato, quindi i dettagli sono incollati qui:

iPhone SDK 3.1.2 (7D11) NSString UIKit Metodo di aggiunte Metodo sizeWithFont restituisce nil

SINTESI sto che decorano UITableViewCells nel metodo delegato UITableView:

  • (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath

Vorrei trovare lunghezza del testo già presente nella cella, per formattare correttamente la nuova vista, in modo che io chiamo il metodo NSString UIKit Aggiunte:

  • (CGSize) sizeWithFont: (UIFont *) carattere constrainedToSize: (CGSize) formato

Quando uso cell.textLabel.font per l'argomento di carattere, restituisce sempre un CGSize vuoto

se uso il metodo DISAPPROVATO, cell.font per l'argomento, fa ritornare il CGSize valore come previsto.

PASSI PER LA RIPRODUZIONE 1.Creare un UITableViewController con un TableView e popolarlo con alcuni dati di esempio 2. Nel metodo stoppato cellForRowAtIndexPath, dopo il commento // Configura la cella e dove è popolato cell.textLabel.text, inserisci quanto segue:


CGSize size = [cell.textLabel.text sizeWithFont:[[cell textLabel] font] constrainedToSize:CGSizeMake(320, 480)]; 
NSLog(@"cell frame: %f %f", size.width, size.height); 

CGSize size2 = [cell.textLabel.text sizeWithFont:[cell font] constrainedToSize:CGSizeMake(320, 480)]; 
NSLog(@"DEPRECATED cell frame: %f %f", size2.width, size2.height); 

rISULTATI ATTESI

Semmai, ci si aspetta la chiamata che utilizza il metodo obsoleto per recuperare il tipo di carattere, di fallire, o per lo meno, sia per tornare lo stesso risultato.

Risultato effettivo:

2010-01-12 22: 06: 36,645 PrefTest [9659: 207] telaio di cella: 0.000000 0.000000 2010-01-12 22: 06: 36,646 PrefTest [9659: 207] DEPRECATED telaio di cella: 88.000000 24.000000

SOLUZIONE & ISOLATION:

Come osservato, utilizzare il metodo obsoleto per ottenere il carattere. Ma diventa strano!

invertire le due metodi che dato sopra:


CGSize size2 = [cell.textLabel.text sizeWithFont:[cell font] constrainedToSize:CGSizeMake(320, 480)]; 
NSLog(@"DEPRECATED cell frame: %f %f", size2.width, size2.height); 

    CGSize size = [cell.textLabel.text sizeWithFont:[[cell textLabel] font] constrainedToSize:CGSizeMake(320, 480)]; 
NSLog(@"cell frame: %f %f", size.width, size.height); 

I risultati sono ora:

2010-01-12 22: 06: 36,645 PrefTest [9659: 207] telaio di cella: 88,000 mila 24,000 mila 2010-01-12 22: 06: 36.646 PrefTest [9659: 207] Frame cella DEPRECATED: 88.000000 24.000000

Sembra che solo il riferimento [carattere cella] sia sufficiente per forzare il carattere [[testo cella cella]] a funzionare correttamente.

5

Sono completamente d'accordo che è abbastanza fastidioso che dovrebbe essere un bug. Perché i bravi ragazzi di Apple dovrebbero chiedere l'altezza della cella senza assicurarsi che la cella sia completamente installata. Silly! Tuttavia, invece di utilizzare una funzione obsoleta, provare:

[cell layoutIfNeeded]; 

chiama questo metodo ha lo stesso effetto con la cella in fase di realizzazione compresi i confini, caratteri cellule, ecc Pertanto, qualsiasi calcolo dopo questo ha accesso alla completamente configurato cella. Ecco l'intero codice:

-(CGFloat) tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath { 

    // Find the cell for this index path 
    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; 
    CGFloat cellHeight = cell.frame.size.height; 

    // Calculate text size after forcing a layout 
    [cell layoutIfNeeded]; 
    CGSize textSize = [cell.textLabel.text sizeWithFont:cell.textLabel.font constrainedToSize:CGSizeMake(cell.contentView.bounds.size.width, 99999) lineBreakMode:cell.textLabel.lineBreakMode]; 

    // Only change the cell height if the text forces a growth 
    if (textSize.height > cellHeight) { 
    cellHeight = textSize.height; 
    } 

    return cellHeight; 
} 
+0

Non funziona – Dejell

+0

Idea stupefacente. [cell layoutIfNeeded]; funziona alla grande! Le altre soluzioni non funzionano. Molte grazie! – Vyacheslav

3

Usa [myLbl sizeToFit]; per ridimensionare automaticamente l'etichetta.

Ecco il codice di esempio.

UILabel *lbl1, *lbl2; 
    if (cell == nil) { 

    UILabel *lbl1 = [[UILabel alloc] init]; 
      [lbl1 setFont:[UIFont boldSystemFontOfSize:20]]; 
      [cell.contentView addSubview:lbl1]; 
      lbl1.frame = CGRectMake(3, 10, 0, 0); 
      lbl1.tag = 10; 
      [lbl1 release]; 

     UILabel *lbl2 = [[UILabel alloc] init]; 
     [lbl2 setFont:[UIFont systemFontOfSize:20]]; 
     [cell.contentView addSubview:lbl2];     
     lbl2.tag = 20; 
     [lbl2 release]; 
} 
else { 
     lbl1 = (UILabel*)[cell.contentView viewWithTag:10]; 
     lbl2 = (UILabel*)[cell.contentView viewWithTag:20]; 
} 

    lbl1.text = @"Hello "; 
    [lbl1 sizeToFit]; 

lbl2.text = @"World"; 
     [lbl2 sizeToFit]; 
     lbl2.frame = CGRectMake(lbl1.frame.origin.x+lbl1.frame.size.width+5, 
           lbl1.frame.origin.y, 
           lbl2.frame.size.width, 
           lbl1.frame.size.height); 
Problemi correlati