2010-11-21 18 views
7

Mam UITableView, który używa niestandardowych UITableViewCell s. Komórki mogą mieć jeden z trzech typów obrazów tła (ustawionych we właściwości każdej komórki: .backgroundView.image): górny, środkowy lub dolny. Górne i dolne obrazy są dla pierwszej i ostatniej komórki i mają zaokrąglone rogi (podobnie jak zgrupowane komórki UITableView). Wszystkie inne "środkowe" komórki wewnątrz UITableView mają prostokątny środkowy obraz tła.Ponowne ładowanie niestandardowego UITableViewCell po zmianie kolejności komórek

Mój problem polega na tym, że podczas porządkowania komórek w trybie Edycja komórki nie odświeżają się z innym obrazem tła w zależności od ich nowej lokalizacji. Na przykład, jeśli przesunę pierwszą komórkę na środek stołu, nadal zachowuje ona swój pierwotny "górny" obraz tła (z zaokrąglonymi narożnikami), a nowa komórka wyświetlana u góry widoku tabeli nadal ma swój pierwotny "środek" obraz tła, który wygląda trochę dziwnie.

Mogę to obejść wykonując reloadData w widoku tabeli, ale ma to problem z nie dostarczaniem ładnej, pełnej wdzięku animacji zmian. Zauważyłem, że gdy zmienia się standardową grupę zgrupowanych UITableView, gdy tylko komórka zostanie przeniesiona/przeciągnięta, obraz tła na odpowiednich komórkach zmienia się (nawet zanim przeniesiona komórka została upuszczona w nowe miejsce), co wygląda bardzo ładnie. Chciałbym osiągnąć to samo.

W tym celu zaimplementowałem tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath, która jest wywoływana za każdym razem, gdy wiersz jest przeciągany w widoku tabeli. W ramach tej próby wypróbowałem różne metody ustawiania backgroundView.image, w tym bezpośrednio ustawiając obraz, a następnie wyraźnie mówiąc, aby przerysować komórkę i/lub obraz przy użyciu setNeedsLayout i setNeedsDisplay, ale nic nie wydaje się przerysowywać komórki. Mam NSLog "wyniki tych zmian i wydają się być zatwierdzanie do komórki, ponieważ prawidłowe wartości pojawiają się w NSLog, ale komórka po prostu nie wydaje się aktualizować na ekranie.

Jeśli ktokolwiek mógłby wskazać, co robię źle, lub zaproponować lepszy sposób osiągnięcia dobrego wyniku, byłbym bardzo wdzięczny. Dzięki!

EDIT: poniższy kod został wyciągnięty z dobroci i sformatowane tak może być łatwiej trawione:

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

Możesz spróbować zamaskować widok stołowy z innym widokiem na nim. Wtedy w ogóle nie będziesz potrzebował obrazów backgorund dla komórek. – Eimantas

+0

Czy mógłbyś wyjaśnić ten pomysł nieco więcej? Nie do końca rozumiem, jak to działa. – Skoota

+0

Powiązane pytanie: http://stackoverflow.com/questions/7338161/update-old-new-top-bottom-cells-backgroundview-when-inserting-deleting-top-bott – an0

Odpowiedz

0

nie próbowałem sam, ale dlaczego nie sprawdzić swoją wartość indexPath.row na metodzie cellForRowAtIndexPath i podać różne wartości backgroundView.image dla pierwszego i ostatniego rzędu?

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

Mam nadzieję, że to pomoże. Cheers, Rog

+0

Hi Rog. Właśnie to robię, ale 'cellForRowAtIndexPath' nie jest wywoływany, gdy wiersz jest przenoszony, ponieważ wiersz jest już na ekranie. Próbowałem ręcznie wywoływanie 'cellForRowAtIndexPath' w metodzie' tableView: targetIndexPathForMoveFromRowAtIndexPath: toProposedIndexPath', ale nic się nie dzieje (tj. Komórka nie przeładowuje/nie przerysowuje na ekranie). – Skoota

1

Jeśli chcesz po prostu odświeżyć kilka komórek raczej całej tabeli można użyć:

reloadRowsAtIndexPaths:withRowAnimation: 

dostępny jako metoda instancji UITableView.

+0

Witaj Robert. Próbowałem, ale to nie zadziała w metodzie 'tableView: targetIndexPathForMoveFromRowAtIndexPath: toProposedIndexPath' (tj. Podczas przeciągania/przeciągania wiersza) i ulega awarii z komunikatem, że liczba wierszy i sekcji po animacji musi być zgodna z liczbą przed animacją. Nic dziwnego, biorąc pod uwagę, że wiersze są nadal przenoszone, gdy próbujemy wywołać tę metodę. – Skoota

+0

Czy próbowałeś ponownie załadować w metodzie UITableViewDataSource 'tableView: moveRowAtIndexPath: toIndexPath:' zamiast tego? Myślę, że jeden jest wywoływany po zakończeniu ruchu. –

+0

Cześć Robert. Przepraszam za spóźnioną odpowiedź. Próbowałem tego również, ale powoduje to dziwne zachowanie. Jeśli przeładuję tylko 'toIndexPath', to sprawi, że wiersz w' fromIndexPath' całkowicie zniknie. Jeśli przeładuję obie ścieżki indeksu, to naprawdę dojdzie do siana i zacznę umieszczać wiele kopii komórek na sobie! – 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)

miałem ten sam problem podczas aktualizacji komórki szczegół etykiety tekst po kolejność.

I rozwiązać go za pomocą następującego kodu:

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

Zauważ, że musisz zaktualizować komórki w fromIndexPath, ponieważ wydaje się, że stan wewnętrznej tableview nie aktualizuje aż ta metoda zwraca . Jeśli otrzymasz komórkę pod numerem toIndexPath, po zakończeniu zmiany kolejności zobaczysz, że komórka sąsiada zostanie zaktualizowana. (górny lub dolny).

1

Spróbuj tego:

[tableView beginUpdates]; 
[tableView endUpdates]; 
0

Apis za częściowo przeładunek wiersze w SDK ios nie działa dobrze (dlatego ppl śledzić ten post tutaj)

I kończy się przy użyciu timera, aby przeładować całe dane po zakończeniu zmiany kolejności animacji. To działa dla mnie.

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 
{ 
    //things to be done when reordering rows 
    .... 


    //issue a timer to reload data 
    NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval: 0.1 
              target: self 
              selector:@selector(updateRow) 
              userInfo: nil repeats:NO]; 


} 


-(void) updateRow 
{ 

    [self.table reloadData]; 

} 
+0

nie musisz używać timera - możesz po prostu użyć '-performSelectorOnMainThread:' – nielsbot

4

Napisz poniżej kod w swoim projekcie i powinien działać zgodnie z oczekiwaniami.

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

To działało idealnie! Mój widok akcesoriów zniknął, ale myślałem o zrobieniu niestandardowego. –

+0

Tak więc, jeśli przeciągniesz wiersz do innego wiersza, a następnie zdecydujesz, że nie chcesz tego przed zwolnieniem przeciągnięcia, obraz zmienia się na nieprawidłowy obraz komórki: / –

Powiązane problemy