2010-11-21 12 views
7

Ich habe UITableView, die benutzerdefinierte UITableViewCell s verwendet. Die Zellen können eine von drei Arten von Hintergrundbildern haben (festgelegt in der Eigenschaft .backgroundView.image jeder Zelle): oben, Mitte oder unten. Die oberen und unteren Bilder sind für die erste und die letzte Zelle und haben abgerundete Ecken (ähnlich wie eine gruppierte UITableView Zellen). Alle anderen "mittleren" Zellen innerhalb der UITableView haben ein rechteckiges mittleres Hintergrundbild.Nachladen benutzerdefinierter UITableViewCell nach Neuanordnen von Zellen

Mein Problem ist, dass bei der Neuordnung der Zellen in UITableViewEdit Modus die Zellen nicht mit einem anderen Hintergrundbild je nach ihrem neuen Speicherort aktualisieren. Wenn ich zum Beispiel die erste Zelle in die Mitte der Tabelle verschiebe, behält sie immer noch ihr ursprüngliches "oberes" Hintergrundbild (mit abgerundeten Ecken) und die neue Zelle, die oben in der Tabellenansicht erscheint, hat immer noch ihre ursprüngliche "Mitte" Hintergrundbild, das alles ein bisschen seltsam aussieht.

Ich kann dies umgehen, indem Sie eine reloadData in der Tabellenansicht, aber das hat das Problem, nicht eine schöne anmutige Animation der Änderungen zu geben. Ich habe festgestellt, dass beim Neuanordnen eines Standards gruppiert UITableView, sobald eine Zelle bewegt/gezogen wird das Hintergrundbild auf den relevanten Zellen ändern (noch bevor die verschobene Zelle wurde an seinen neuen Standort fallen gelassen), die sehr schön aussieht. Ich möchte das Gleiche erreichen.

Zu diesem Zweck habe ich tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath implementiert, die jedes Mal aufgerufen wird, wenn eine Zeile in der Tabellenansicht gezogen wird. In diesem habe ich verschiedene Methoden der Einstellung der backgroundView.image einschließlich nur direkt das Bild einstellen und dann auch explizit gesagt, um die Zelle und/oder Bild neu zu zeichnen mit setNeedsLayout und setNeedsDisplay, aber nichts scheint die Zelle neu zu zeichnen. Ich habe NSLog 'ged die Ergebnisse dieser Änderungen und sie scheinen sich auf die Zelle zu verpflichten, wie die richtigen Werte in der NSLog erscheinen, aber die Zelle scheint nur nicht auf dem Bildschirm zu aktualisieren.

Wenn jemand darauf hinweisen könnte, was ich falsch mache, oder einen besseren Weg vorschlagen, ein Arbeitsergebnis zu erreichen, würde ich sehr dankbar sein. Vielen Dank!

EDIT: der folgende Code wurde aus der Fülle und formatierte gezogen, so dass es leichter verdaut werden kann:

UIImage *rowBackground; 
UIImage *selectionBackground; 
NSInteger sectionRows = [_tableView numberOfRowsInSection:[indexPath section]]; 
NSInteger row = [indexPath row]; 
if (row == 0 && row == sectionRows - 1) 
{ 
    rowBackground = [UIImage imageNamed:@"field_title_bkg.png"]; 
    selectionBackground = [UIImage imageNamed:@"field_title_bkg.png"]; 
} 
else if (row == 0) 
{ 
    rowBackground = [UIImage imageNamed:@"table_row_top_bkg.png"]; 
    selectionBackground = [UIImage imageNamed:@"table_row_top_bkg.png"]; 
} 
else if (row == sectionRows - 1) 
{ 
    rowBackground = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; 
    selectionBackground = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; 
} 
else 
{ 
    rowBackground = [UIImage imageNamed:@"table_row_bkg.png"]; 
    selectionBackground = [UIImage imageNamed:@"table_row_bkg.png"]; 
} 
UIImageView *rowBackGroundImageView = [[UIImageView alloc] initWithImage:rowBackground]; 
UIImageView *rowBackGroundSelectionImageView = [[UIImageView alloc] initWithImage:selectionBackground]; 
if (row != sectionRows - 1) 
{ 
    UIImageView *sep = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cell_separator.png"]]; 
    [sep setFrame:CGRectMake(20, 56, 280, 1)]; 
    [rowBackGroundImageView addSubview:sep]; 
} 
[cell setBackgroundView:rowBackGroundImageView]; 
[rowBackGroundImageView release]; 
+0

Sie können versuchen, die Tabellenansicht mit einer anderen Ansicht darüber zu maskieren. Dann brauchen Sie keine Hintergrundbilder für Zellen. – Eimantas

+0

Können Sie diese Idee ein bisschen mehr erklären? Ich verstehe nicht ganz, wie das funktionieren würde. – Skoota

+0

Eine verwandte Frage: http://stackoverflow.com/questions/7338161/update-old-new-top-bottom-cells-backgroundview-when-inserting-deleting-top-bott – an0

Antwort

0

Ich habe mich nicht versucht, aber warum nicht Ihren indexPath.row Wert auf der cellForRowAtIndexPath Methode testen und die verschiedenen backgroundView.image-Werte für die erste und letzte Zeile angeben?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

Ich hoffe, das hilft. Cheers, Rog

+0

Hallo Rog. Das mache ich gerade, aber 'cellForRowAtIndexPath' wird nicht aufgerufen, wenn die Zeile verschoben wird, da die Zeile bereits auf dem Bildschirm ist. Ich habe versucht, 'cellForRowAtIndexPath' in der Methode 'tableView: targetIndexPathForMoveFromRowAtIndexPath: toProposedIndexPath' manuell aufzurufen, aber nichts passiert (d. H. Die Zelle wird nicht neu geladen/neu gezeichnet). – Skoota

1

Wenn Sie nur ein paar Zellen neu laden wollen vielmehr die gesamte Tabelle, die Sie verwenden können:

reloadRowsAtIndexPaths:withRowAnimation: 

erhältlich als Instanzmethode von UITableView.

+0

Hallo Robert. Versuchte das, aber es funktioniert nicht in der 'tableView: targetIndexPathForMoveFromRowAtIndexPath: toProposedIndexPath' Methode (dh während die Zeile gezogen/bewegt wird) und stürzt mit der Meldung ab, dass die Anzahl der Zeilen und Abschnitte nach der Animation mit der Zahl übereinstimmen muss vor der Animation. Kein Wunder, denn die Zeilen werden immer noch verschoben, wenn wir diese Methode aufrufen. – Skoota

+0

Haben Sie versucht, das Neuladen in der UITableViewDataSource-Methode 'tableView: moveRowAtIndexPath: toIndexPath:' durchzuführen? Ich denke, dass man nach dem Umzug aufgerufen wird. –

+0

Hallo Robert. Entschuldigung wegen der späten Antwort. Ich habe das auch versucht, aber es verursacht ein seltsames Verhalten. Wenn ich 'toIndexPath' nur neu lade, wird die Zeile bei' fromIndexPath' vollständig verschwinden. Wenn ich beide Indexpfade neu lade, wird es wirklich Heu-Draht und beginnen, mehrere Kopien von Zellen übereinander zu legen! – Skoota

0

(this solution only works for the reordering of rows within the same section. It'll fail when dragging and dropping rows to a different section)

Ich hatte das gleiche Problem, wenn nach einer Zelle Detail Beschriftungstext Aktualisierung neu geordnet werden.

Ich löste es mit dem folgenden Code:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 
{ 
UITableViewCell* cell = [self.table cellForRowAtIndexPath:fromIndexPath]; 
cell.detailTextLabel.text = @"NEW STRING"; 
} 

Beachten Sie, dass die Zelle an fromIndexPath zu aktualisieren, weil es scheint, dass der innere Zustand des Tableview nicht bis dieser Methode nicht aktualisiert . Wenn Sie die Zelle bei toIndexPath erhalten, nachdem die Neuordnung abgeschlossen ist, sehen Sie, dass die Nachbarzelle aktualisiert wird. (entweder oben oder unten).

1

Versuchen Sie folgendes:

[tableView beginUpdates]; 
[tableView endUpdates]; 
0

APIS für teilweise Zeilen in der ios sdk Nachladen gut funktioniert nicht (das ist, warum ppl diesen Beitrag folgen hier)

ich mit Timer am Ende der nachzuladen ganze Daten nach Neuanordnen der Animation beendet. Es funktioniert für mich.

+0

nicht sicher, dass Sie einen Timer verwenden müssen - Sie können einfach verwenden -performSelectorOnMainThread: ' – nielsbot

4

Schreiben Sie unter Code in Ihrem Projekt und es sollte wie erwartet funktionieren.

- (NSIndexPath *)tableView:(UITableView *)tableView 
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath 
     toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath 
{ 
    NSInteger sectionRows = [tableView numberOfRowsInSection:[sourceIndexPath section]]; 

    UITableViewCell *sourceCell = [tableView cellForRowAtIndexPath:sourceIndexPath]; 
    UITableViewCell *destCell = [tableView cellForRowAtIndexPath:proposedDestinationIndexPath]; 

    if(sourceIndexPath.row == 0 && proposedDestinationIndexPath.row == 1) 
    { 
     ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; 

     if(proposedDestinationIndexPath.row == sectionRows - 1) 
      ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; 
     else 
      ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; 
    } 

    else if(sourceIndexPath.row == sectionRows - 1 && proposedDestinationIndexPath.row == sectionRows - 2) 
    { 
     ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; 

     if(proposedDestinationIndexPath.row == 0) 
      ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; 
     else 
      ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; 
    } 

    else if(proposedDestinationIndexPath.row == 0) 
    { 
     ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; 

     destCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:proposedDestinationIndexPath.section]]; 
     if(sectionRows == 2) 
      ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; 
     else 
      ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; 
    } 

    else if(proposedDestinationIndexPath.row == sectionRows - 1) 
    { 
     ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; 

     destCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:sectionRows - 1 inSection:proposedDestinationIndexPath.section]]; 
     if(sectionRows == 2) 
      ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; 
     else 
      ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; 
    } 

    return proposedDestinationIndexPath; 
} 
+0

Das hat perfekt funktioniert! Meine Accessoire-Ansicht scheint verschwunden zu sein, aber ich dachte sowieso daran, einen Custom-Look zu machen. –

+0

Also, wenn Sie eine Zeile in eine andere Zeile ziehen, dann entscheiden Sie, dass Sie es dort nicht wollen, bevor Sie den Ziehvorgang loslassen, das Bild ändert sich in das falsche Zellbild: / –

Verwandte Themen