2010-11-28 5 views
1

Ich habe versucht, zuerst die Antwort hier zu finden, aber ich bin fest. Ich habe ein UITableView-Set mit UITableViewStyleGrupped mit 4 Abschnitten mit jeweils einer oder zwei Zeilen. In zwei der Abschnitte brauchte ich eine Reihe, um eine größere Höhe zu haben, um den Inhalt zu halten, den ich dort festhalte.Gruppierte UITableView Zeilen mit unterschiedlichen Höhen verursacht Inhalt Shuffle

Sieht gut aus, außer wenn ich scroll rauf und runter, beginnen TextLabels, Zubehör und zusätzliche Subviews in verschiedene Rowss verschieben und ich kann nicht herausfinden, warum.

Diese screenshot zeigt die Tabellenansicht, wenn es lädt und dann ich ein paar Mal nach oben und unten scrollen. Jedes Mal scrollte ich verschiedene Reiheninhaltmischungen.

Ich dachte, ich lese etwas über dieses Problem mit dem gruppierten Stil. Natürlich sehe ich dieses Problem nicht, wenn ich den Tabellenstil auf Standard umstelle. Darf ich die Höhe für einige Zeilen bei Verwendung des gruppierten Stils nicht dynamisch festlegen?

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == kSection_Info && indexPath.row == kSectionRow_InfoPhoto) 
    { 
     return 84.0; 
    } 
    else if (indexPath.section == kSection_Level && indexPath.row == kSectionRow_LevelLevel) 
    { 
     return 70.0; 
    } 
    return 44.0; 
} 

Ich gründe jede Zeile manuell in celForRowAtIndexPath up:

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) 
    { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     switch (indexPath.section) 
     { 
      case kSection_Info: 
      { 
       switch (indexPath.row) 
       { 
        case kSectionRow_InfoName: 
        { 
         cell.textLabel.text = @"Name"; 
         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
         self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(74, 8, 195, 25)]; 
         self.nameLabel.textAlignment = UITextAlignmentRight; 
         self.nameLabel.font = [UIFont systemFontOfSize:16]; 
         self.nameLabel.textColor = [UIColor blueColor]; 
         self.nameLabel.text = self.currentRecipient.fullName;      
         [cell.contentView addSubview:self.nameLabel]; 

         break; 
        } 
        case kSectionRow_InfoPhoto: 
        { 
         cell.textLabel.text = @"Photo"; 
         self.imageButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
         self.imageButton.frame = CGRectMake(10, 14, 64, 64); 
         [self.imageButton addTarget:self action:@selector(onImageButtonTouch:) forControlEvents:UIControlEventTouchUpInside];     

         NSString *imageName = @"add_image.png"; 
         UIImage *thumb = [UIImage imageNamed:imageName]; 
         [self.imageButton setImage:thumb forState:UIControlStateNormal]; 
         cell.accessoryView = self.imageButton; 

         break; 
        } 
        default: 
        { 
         break; 
        } 
       } 
       break; 
      } 

      case kSection_List: 
      { 
       switch (indexPath.row) 
       { 
        case kSectionRow_ListHasList: 
        { 
         cell.textLabel.text = @"Is Listed";     
         self.listSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; 
         cell.accessoryView = self.listSwitch;     

         break; 
        } 
        case kSectionRow_ListBudget: 
        { 
         cell.textLabel.text = @"List Amount"; 
         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
         self.budgetLabel = [[UILabel alloc] initWithFrame:CGRectMake(124, 8, 145, 25)]; 
         self.budgetLabel.textAlignment = UITextAlignmentRight; 
         self.budgetLabel.font = [UIFont systemFontOfSize:16]; 
         self.budgetLabel.textColor = [UIColor blueColor]; 
         self.budgetLabel.text = [@"$" stringByAppendingFormat:@"%0.2f", [self.currentRecipient.budget floatValue]];      
         [cell.contentView addSubview:self.budgetLabel]; 

         break; 
        } 
        default: 
        { 
         break; 
        } 
       } 
       break; 
      } 

      case kSection_Level: 
      { 
       switch (indexPath.row) 
       {    
        case kSectionRow_LevelLevel: 
        { 
         self.levelSlider = [[UISlider alloc] initWithFrame:CGRectMake(8, 2, 284, 40)]; 
         self.levelSlider.minimumValue = 0.0; 
         self.levelSlider.maximumValue = 100.0; 
         self.levelSlider.continuous = YES; 

         UIImage *meterImage = [UIImage imageNamed:@"meter_labels.png"]; 
         UIImageView *meterView = [[UIImageView alloc] initWithFrame:CGRectMake(8, 32, 284, 24)]; 
         [meterView setImage:meterImage]; 

         [cell.contentView addSubview:self.levelSlider]; 
         [cell.contentView addSubview:meterView]; 
         [meterImage release]; 

         break; 
        } 
        case kSectionRow_LevelHasLevel: 
        { 
         cell.textLabel.text = @"Show Level"; 
         self.levelSwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease]; 
         cell.accessoryView = self.levelSwitch;        
         break; 
        }      
        default: 
        { 
         break; 
        } 
       } 
       break; 
      } 

      case kSection_RecipientDelete: 
      { 
       cell.textLabel.text = @"Delete Recipient";   
       cell.textLabel.textAlignment = UITextAlignmentCenter; 
       cell.textLabel.textColor = [UIColor blueColor];    
       break; 
      } 

      default: 
      { 
       break; 
      } 
     } 
    } 

    return cell; 
} 
+0

Wie sieht Ihre 'tableView: cellForRowAtIndexPath:' Methode aus? –

+0

Hinzugefügt zu meiner Frage, danke! – bread

Antwort

0

Der „Inhalt schlurfenden“ Sie sehen, ist höchstwahrscheinlich durch unsachgemäße Handhabung von Zell Wiederverwendung.

Es gibt kein Problem speziell mit dem gruppierten Stil. Das Problem wird sich eher in diesem Stil manifestieren, da weniger Zellen in den Bildschirm passen, was mehr Scrollen erfordert und mehr Wiederverwendung von Zellen erfordert.

Sie richten den Zelleninhalt nur beim Erstellen von Zellen ein (wenn Zelle == Nil). Wenn eine Zelle über den Bildschirm scrollt, wird sie in die Warteschlange für die Wiederverwendung verschoben. Die Zeile am anderen Ende, die nun sichtbar ist, verwendet die Zellenansicht, die sich in der Wiederverwendungswarteschlange befindet. Die wiederverwendete Zelle enthält den Inhalt einer anderen Zeile.

Wenn alle Zellen gleich sind (zumindest in Bezug auf die UI-Steuerelemente und nicht die Daten), ist dies kein Problem. Wenn alle oder einige der Zellen unterschiedlich sind, erhalten Sie Steuerelemente, die Sie nicht erwarten.


Da Sie nur eine kleine Anzahl von Zeilen und jede ist anders gelegt aus, die schnell (und vielleicht schmutzig) Lösung ist eine andere Wiederverwendungs ​​Kennung für jede Zelle wie folgt zu verwenden:

NSString *CellIdentifier = 
    [NSString stringWithFormat:@"RecipientEntryCell-%d-%d", 
    indexPath.section, indexPath.row]; 

Dies ist überhaupt nicht zu empfehlen, wenn die Tabellenansicht viele verschiedene Zellen enthalten soll, da jede Zelle für jede Zeile in der Tabelle gleichzeitig im Speicher ist (anstatt nur die wenigen auf dem Bildschirm). Verwenden Sie keinen eindeutigen Bezeichner, um alle Probleme bei der Wiederverwendung von Zellen zu lösen.

Der Tabellenansicht-Programmierleitfaden zeigt eine alternative Möglichkeit, Tabellenansichten wie diese zu entwerfen, in denen Sie einige Zellen mit unterschiedlichen Layouts haben. Siehe "Die Technik für den statischen Zeileninhalt" unter this page.


Letztendlich ist es besser, wenn Sie verstehen, dass die Tabellenansicht Zellen aus guten Gründen wiederverwendet und nicht versucht, sie ständig zu umgehen.Im allgemeinen sollte die cellForRowAtIndexPath wie folgt aussehen:

static NSString *CellIdentifier = @"CellIdentifier"; 

UITableViewCell *cell = [tableView dequeueReusableCell... 
if (cell == nil) { 
    //Create cell... 
    //Set UI content that applies to all rows (if any)... 
} 
else { 
    //Cell is being re-used. 
    //Remove UI content that doesn't apply to this row... 
} 

//Add UI content that applies only to this row... 

//Copy values from data source to cell UI controls... 

return cell; 

Wenn Sie die Zellen konstruieren, wie oben gezeigt, nicht auf Klassenebene Verweise auf UI-Steuerelemente innerhalb der Zellen halten (wie nameLabel, Image, etc). Stattdessen sollten die Steuerwerte in cellForRowAtIndexPath aus einer Hintergrunddatenvariablen (Modell) festgelegt werden und der Wert sollte in die Hintergrunddatenvariable gelesen oder gespeichert werden, sobald sich das Oberflächensteuerelement ändert.

Beispiel: Anstatt einen Verweis auf einen UISlider in einer Zelle zu speichern, speichern Sie den aktuellen Schiebereglerwert als Float-Ivar. Initialisiere die Gleitkomma gegebenenfalls (z. B. viewDidLoad). Erstellen Sie in cellForRowAtIndexPath den UISlider, legen Sie seinen Wert mithilfe des Float-Ivar fest und lassen Sie den Schieberegler eine Methode aufrufen, wenn sich der Wert ändert. Kopieren Sie in dieser Methode den Wert des Schiebereglers in den Float-Bereich.

Hoffe, das hilft.

+0

Vielen Dank für die ausführliche Antwort. Ich habe einige Tests gemacht, als ich versuchte zu debuggen und das gleiche zu realisieren. Mein aktuelles Problem hat nichts mit dem Tabellenstil oder der Zeilenhöhe zu tun. Hat alles damit zu tun, dass ich nicht den richtigen Ansatz zum Erstellen von Tabellen mit unterschiedlichem statischen Inhalt kenne. Ich wollte eigentlich nur den Tisch für Layout und Stil und deshalb macht es mir nichts aus, die einzigartigen Zellen in IB zu bauen. Ich werde Ihren Ratschlag zur Vermeidung von Referenzen auf Klassenebene mitnehmen – bread

Verwandte Themen