Расширяющиеся ячейки табличного представления исчезают - PullRequest
17 голосов
/ 22 февраля 2012

У меня есть ячейки, которые расширяются путем изменения их высоты с помощью вызова метода setExpanded:

Затем я вызываю reloadRowsAtIndexPaths: для обновления ячеек.

Проблема заключается в том, что ячейки просто исчезают и случайным образомвновь появляются.Я подозреваю, что это связано с тем, как работает индексация.

Если я вызываю reloadData или beginUpdates / endUpdates, ячейки работают как положено, но я теряю анимацию.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    JVCell *cell = (JVCell*)[tableView cellForRowAtIndexPath:indexPath];
    JVCell *previousCell = nil;

    if( previousIndexPath_ != nil ) // set to nil in viewDidLoad
    {
        previousCell = (JVCell*)[tableView cellForRowAtIndexPath:previousIndexPath_];
    }


    // expand or collapse cell if it's the same one as last time
    if( previousCell != nil && [previousIndexPath_ compare:indexPath] == NSOrderedSame && [previousCell expandable] )
    {
        [previousCell setExpanded:![cell expanded]];
        NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_];
        [tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
    }
    else
    {
        // collapse previous cell
        if( previousCell != nil && [previousCell expandable] )
        {
            if( [previousCell expanded] ) [previousCell setExpanded:NO];
            NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_];
            [tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
        }

        // expand new cell
        if( [cell expandable] )
        {
            [cell setExpanded:YES];
            NSArray *indexPathArray = [NSArray arrayWithObject:indexPath];
            [tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
        }
    }

    previousIndexPath_ = indexPath;

    // works as expected, but I lose the animations
    //[tableView reloadData];

    // works as expected, but I lose the animations
    //[tableView beginUpdates];
    //[tableView endUpdates];
}

РЕДАКТИРОВАТЬ: обновлено, чтобы включить методы cellForRowAtIndexPath и heightForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];
    JVCellSectionData *sectionData = [sections_ objectAtIndex:section]; // NSArray of SectionData objects
    NSArray *cellArray = [sectionData cells]; // NSArray of cells
    UITableViewCell *cell = [cellArray objectAtIndex:row];
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];
    JVCellSectionData *sectionData = [sections_ objectAtIndex:section];
    NSArray *cellArray = [sectionData cells];
    JVCell *cell = [cellArray objectAtIndex:row];
    return [cell cellHeight]; // changed when selected with setExpanded: method
}

Редактировать 2: Я сделал Quicktime-видео о происходящем и извлек снимки экрана.

Я пытаюсь расширить ячейку, а не заменять, вставлять или удалять ячейки.Каждая ячейка имеет одно или несколько подпредставлений.Высота ячейки изменяется в зависимости от того, «расширена» она или нет.К представлению содержимого добавлены подпредставления, и его свойство clipToBounds имеет значение YES.Когда ячейки расширяются или сворачиваются, значение высоты изменяется вместе с рамкой ячейки (включая вид фона и выбранный вид фона).Я зарегистрировал все значения кадров до, во время и после расширения, и все они соответствуют их состоянию и положению.

sectioned table view design

cell tapped

cell expanding

cell disappeared

cell retracts

cell visible again

Имейте в виду, что это нормально работает на iOS 4.3, как показано ниже:

comaprison ios 4 to ios 5

Ответы [ 7 ]

7 голосов
/ 28 февраля 2012

Я не вижу никакой разницы в поведении между iOS 5.0 и 4.3.2 в симуляторе или 5.0 в моем телефоне - ячейки исчезают одинаково на каждом.(Я бы проверил 4.2.1 на моем старом iPod touch, но Xcode 4 не может. Grr ..) Похоже, что есть простой обходной путь: хотя, если вы сделаете оба reloadRowsAtIndexPaths: withRowAnimation: после расширения / сворачивания ваших ячеек изатем вызов reloadData после этого, похоже, для сохранения анимации.

Вот небольшой демонстрационный проект для этого.Трудно сказать, какова была настоящая проблема - это просто какой-то странный побочный эффект от того, как UIKit выполняет анимацию ячейки.Если вы создаете подкласс [UITableViewCell setAlpha:], вы можете видеть, что табличное представление устанавливает альфа-ячейку в 0 и оставляет его там.Странно.

Редактировать: Ну, это странно.Это не работало некоторое время (занималось старым поведением, с исчезновением клеток), но теперь это снова правильно.Может быть, я работал не ту версию.В любом случае, дайте мне знать, если это работает для вас.

5 голосов
/ 12 ноября 2012

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

Но оказывается, что проблема вызвана возвратом кэшированного UITableViewCell в cellForRowAtIndexPath, когда на самом деле нужен свежий.

Документ для reloadRowsAtIndexPaths: withRowAnimation: говорит: «При перезагрузке строки табличное представление запрашивает у своего источника данных новую ячейку для этой строки».

Ваш метод cellForRowAtIndexPath возвращает локально кэшированные ячейки. Возвращение новой ячейки решило проблему в моем случае, и никаких обходных путей не требовалось ...

2 голосов
/ 01 марта 2012

@ Javy

Спасибо за ваш вопрос. Я разрабатывал таблицу с похожим поведением: в моих ячейках табличного представления (UITableViewCell) есть текстовые представления (*1004*):

  1. расширение, если для отображения текста без прокрутки требуется новая строка, или
  2. разваливается, если была удалена новая строка

Итак, я обнаружил ту же проблему. В iOS 5.x , когда я начинал печатать текст, он внезапно становился невидимым. Но в iOS 4.x все отлично работает.

Я нашел решение, и оно хорошо работает для меня.

Решение: Просто попробуйте заменить тип анимации UITableViewRowAnimationAutomatic на UITableViewRowAnimationNone при перезагрузке конкретной ячейки.

Дополнительный код: перезагрузите обе ячейки в один момент:

    NSMutableArray *indexes = [NSMutableArray arrayWithCapacity:2];
    // collapse previous cell
    if( previousCell != nil && [previousCell expandable] )
    {
        if( [previousCell expanded] ) [previousCell setExpanded:NO];
        [indexes addObject:previousIndexPath_];
    }

    // expand new cell
    if( [cell expandable] )
    {
        [cell setExpanded:YES];
        [indexes addObject:indexPath];
    }

    [tableView reloadRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationNone];

Надеюсь, это поможет вам.

0 голосов
/ 10 апреля 2012

In:

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

Вы должны вернуть новую ячейку.Если ячейка не нужна для создания новой, вам нужно только:

[tableView beginUpdates];
[tableView endUpdates];

Нет необходимости звонить reloadRowsAtIndexPaths.

0 голосов
/ 01 марта 2012

вы могли бы попытаться перезагрузить табличное представление, когда анимация завершится? в данный момент, если ваши анимации запускаются, а затем вы вызываете [tableView reloadData], анимации не будут завершены, поэтому кадр и т. д. могут выйти из синхронизации

вы можете изменить свой расширенный метод set, чтобы взять флаг, а также блок завершения анимации, который может содержать код перезагрузки

[cell setExpanded:YES completion:^
    //reload code
}];
0 голосов
/ 01 марта 2012

Мне кажется, что клетка перерисована неправильно.

Вы пробовали что-то вроде:

[cell.backgroundView setNeedsDisplay]
0 голосов
/ 23 февраля 2012

Ладно ...

перед вами

previousIndexPath_ = indexPath;

и после того, как вы сделаете все расширение / сжатие высот и т. Д .;вам нужно сделать что-то вроде

[cellArray replaceObjectAtIndex:previousIndexPath_ withObject:previousCell];
[cellArray replaceObjectAtIndex:indexPath withObject:cell];

, что означает, что ваш cellArray должен быть

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