Перезагрузка пользовательского UITableViewCell после переупорядочения ячеек - PullRequest
7 голосов
/ 21 ноября 2010

У меня есть UITableView, который использует пользовательские UITableViewCell с. Ячейки могут иметь один из трех типов фоновых изображений (задается в свойстве .backgroundView.image каждой ячейки): верх, середина или низ. Верхнее и нижнее изображения предназначены для первой и последней ячеек и имеют закругленные углы (очень похоже на сгруппированные ячейки UITableView). Все остальные «средние» ячейки в пределах UITableView имеют прямоугольное среднее фоновое изображение.

Моя проблема заключается в том, что при изменении порядка ячеек в режиме UITableView Правка ячейки не обновляются с другим фоновым изображением в зависимости от их нового местоположения. Например, если я переместил первую ячейку в середину таблицы, она все еще сохраняет свое исходное «верхнее» фоновое изображение (с закругленными углами), а новая ячейка, которая появляется в верхней части представления таблицы, все еще имеет свою первоначальную «середину» фоновое изображение, которое выглядит немного странно.

Я могу обойти это, выполнив reloadData в табличном представлении, но проблема заключается в том, чтобы не дать приятную изящную анимацию изменений. Я заметил, что при переупорядочении стандартного сгруппированного UITableView, как только ячейка перемещается / перетаскивается, фоновое изображение на соответствующих ячейках изменяется (даже до того, как перемещенная ячейка была перемещена в новое место), что выглядит очень хорошо. Я хотел бы добиться того же.

Для этого я реализовал tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath, который вызывается каждый раз, когда строка перетаскивается в табличном представлении. В рамках этого я попробовал различные методы установки backgroundView.image, включая просто прямую настройку изображения, а затем также явно указывал ему перерисовать ячейку и / или изображение, используя setNeedsLayout и setNeedsDisplay, но ничто не заставляет ячейку перерисовываться. Я NSLog 'отредактировал результаты этих изменений, и они, кажется, фиксируются в ячейке, поскольку правильные значения появляются в NSLog, но ячейка просто не обновляется на экране.

Если бы кто-нибудь мог указать, что я делаю неправильно, или предложить лучший способ достижения рабочего результата, я был бы очень признателен. Спасибо!

РЕДАКТИРОВАТЬ: следующий код был извлечен из щедрости и отформатирован, чтобы его можно было легко переварить:

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

Ответы [ 6 ]

4 голосов
/ 16 июля 2012

Напишите ниже код в вашем проекте, и он должен работать в соответствии с ожиданиями.

- (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;
}
1 голос
/ 21 ноября 2011

Попробуйте это:

[tableView beginUpdates];
[tableView endUpdates];
1 голос
/ 21 ноября 2010

Если вы просто хотите перезагрузить несколько ячеек, а не всю таблицу, которую вы можете использовать:

reloadRowsAtIndexPaths:withRowAnimation:

доступно как метод экземпляра UITableView.

0 голосов
/ 22 ноября 2011

API для частичной перезагрузки строк в ios sdk не работает должным образом (поэтому ppl следует этому посту здесь)

В итоге я использую таймер для перезагрузки всех данных после завершения переупорядочения анимации.У меня это работает.

- (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 голосов
/ 21 ноября 2011

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

У меня была такая же проблема при обновлении текста метки детализации ячейки после переупорядочения.

Я решил ее с помощью следующего кода:

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

Обратите внимание, что необходимо обновить ячейку на fromIndexPath, поскольку кажется, что внутреннее состояние табличного представления не обновляется до тех пор, пока не вернется этот метод.Если вы получите ячейку в toIndexPath, то после завершения переупорядочения вы увидите, что соседняя ячейка обновляется.(верхний или нижний).

0 голосов
/ 21 ноября 2010

Я сам не пробовал, но почему бы не проверить значение indexPath.row в методе cellForRowAtIndexPath и предоставить разные значения backgroundView.image для первой и последней строки?

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

Надеюсь, это поможет. Ура, Рог

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...