2009-12-22 18 views
22

Ich erstelle eine benutzerdefinierte, in-Anwendung Einstellungen Ansicht basierend auf UITableViewCellStyle1 (oder so).Dynamische Berechnung der UILabel-Breite in UITableViewCell

Ich versuche, die Breite der linken Bezeichnung (Titel) einer Zelle dynamisch zu berechnen, um zu bestimmen, wie breit mein Textfeld auf der rechten Seite sein kann.

Wenn ich die App im Simulator startet und die Ansicht lädt, ist die Breite der Titelbeschriftungen Null, bis ich die Ansicht durchgeblättert habe und eine Zelle nicht sichtbar ist. Wenn ich dann zurück scrolle, wird die Größe wie erwartet angepasst. Ich glaube, das könnte etwas mit der Wiederverwendung von Zellen zu tun haben.

Ich brauche die Titeletiketten in den Zellen, um ihre korrekte Breite zu haben, wenn die Ansicht geladen wird, nicht nachdem sie einmal außer Sichtweite gegangen sind.

- (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; 
    } 

Antwort

16

Explizit das Setzen der Schriftart löst Ihr Problem.

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

Gory detals:
Wenn die Tableview ersten Laden, dieser Ausschnitt Breite Null zurückkehrt aufgrund der Größe der Schrift 0.

[textLabel.text sizeWithFont:textLabel.font] 

wobei ich dies den Punkt heraus Größe durch die Anzeige die Zellenschrift.

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

Die Punktgröße war Null, bis die Zelle vom Bildschirm verschwunden war und kam zurück, genau wie Sie beschrieben haben.

3

Ich habe das gleiche Problem gefunden, aber ich habe einen Workaround gefunden. FYI Ich habe einen Fehler mit Apple (Bug ID # 7535066) ausgelöst. Lex, in Ihrem Beispiel, wenn Sie cell.font anstelle von textLabel.font verwenden, sollte es funktionieren, obwohl Sie eine Compiler-Warnung erhalten, da dies ein veralteter Methodenaufruf ist. Ich bin mir nicht sicher, ob Sie in der Lage sein werden die Details des Fehlers zu sehen, ich angehoben, so dass ich das Einfügen der Details hier:

iPhone SDK 3.1.2 (7D11) NSString UIKit Zugänge Methode sizeWithFont nil

ZUSAMMENFASSUNG ich Dekoration UITableViewCells im UITableView Delegatmethode:

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

Ich wünsche Länge des Textes finden bereits in der Zelle, um korrekt die neue Ansicht zu formatieren, so dass ich die NSString UIKit Additions-Methode aufrufen:

  • (CGSize) sizeWithFont: (UIFont *) Schriftart constrainedToSize: (CGSize) Größe

Als ich cell.textLabel.font für die Schriftart Argument verwenden, gibt es immer eine leere CGSize

Wenn ich die DEPRECATED Methode, cell.font für das Argument verwenden, ist es die CGSize zurückkehrt Wert wie erwartet.

SCHRITTE ZUR REPRODUZIERUNG 1.Erstellen Sie einen UITableViewController mit einem TableView und füllen Sie ihn mit einigen Beispieldaten. 2. Geben Sie in der Stub-Methode cellForRowAtIndexPath nach dem Kommentar // Richten Sie die Zelle ein und geben Sie an, wo der cell.textLabel.text aufgefüllt wird:


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); 

ERWARTETE ERGEBNISSE

Wenn überhaupt, Sie den Anruf erwarten, dass die veraltete Methode verwendet die Schriftart abzurufen, versagen, oder zumindest beide das gleiche Ergebnis zurück.

tatsächliches Ergebnis:

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

Abhilfe & ISOLATION:

Wie bereits erwähnt, verwendet die veraltete Methode, um die Schriftart zu erhalten. Aber es wird merkwürdiger!

die beiden Methoden Rückwärts I oben haben:


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); 

Die Ergebnisse sind jetzt:

2010-01-12 22: 06: 36,645 PrefTest [9659: 207] Zellrahmen: 88,000000 24,000000 2010-01-12 22: 06: 36.646 PrefTest [9659: 207] DEPERCATED Zellframe: 88.000000 24.000000

Es scheint, dass nur die Bezugnahme [Zellenschriftart] ausreicht, um [[cell textLabel] font] zu erzwingen, ordnungsgemäß zu funktionieren.

5

Ich stimme völlig zu, dass es genug nervig ist, dass es ein Fehler sein sollte. Warum würden die netten Leute von Apple jemals nach der Zellenhöhe fragen, ohne sicherzustellen, dass die Zelle vollständig aufgebaut ist? Dumm! Anstatt jedoch eine veraltete Funktion verwenden, versuchen Sie:

[cell layoutIfNeeded]; 

Aufruf dieser Methode hat den gleichen Effekt mit der Zelle einschließlich der Grenzen aufgebaut wird, Zelle Schriftart usw. Daher wird jede Berechnung nach dieser Anbindung an die Autobahnen vollständig eingerichtete Zelle. Hier ist der gesamte Code:

-(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

Es funktioniert nicht – Dejell

+0

Imazing Idee. [Zelle layoutIfNeeded]; funktioniert super! Die anderen Lösungen funktionieren nicht. Danke vielmals! – Vyacheslav

3

Verwenden [myLbl sizeToFit];, um die Größe des Etiketts automatisch zu ändern.

Hier ist der Beispielcode.

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); 
Verwandte Themen