Подтвердить что ты не робот

Изменение размера ячейки анимации UICollectionView вызывает нежелательное поведение

У меня есть UICollectionViewController, который использует стандартный UICollectionViewFlowLayout для отображения одного вертикального столбца ячеек. Я пытаюсь создать анимацию expand/collapse на ячейке при прослушивании ячейки. Для этого я использую следующий код:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath (NSIndexPath *)indexPath
{
    [self.feedManager setCurrentlySelectedCellIndex:indexPath.item];
    [self.collectionView performBatchUpdates:nil completion:nil];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //Return the size of each cell to draw
    CGSize cellSize = (CGSize) { .width = 320, .height = [self.feedManager heightForCellAtIndexPath:indexPath] };
    return cellSize;
}

Свойство 'selectedCellIndex' на моем управляющем объекте указывает модели данных возвращать расширенный или свернутый размер внутри heightForCellAtIndexpath:

[self.collectionView performBatchUpdates:nil completion:nil];

Затем метод performBatchUpdates:completiong: прекрасно анимирует это изменение размера. Однако! Когда происходит анимация, расширяющаяся ячейка может вызвать частично видимую ячейку в нижней части экрана, чтобы выйти из экрана.

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

Я бы предпочел, чтобы все ячейки оживлялись вместе, независимо от того, находятся ли они вне экрана или нет. Любые мысли?

4b9b3361

Ответ 1

Это ошибка UICollectionViewFlowLayout, но есть обходной путь. Проблема в том, что атрибуты, возвращаемые initialLayoutAttributesForAppearingItemAtIndexPath:, имеют неправильные фреймы. В частности, у них есть кадры конечного, на экране, а не на начальном, выключенном экране. Вам просто нужно переопределить этот метод и вернуть правильные кадры. Основная структура переопределения будет выглядеть примерно так:

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
    UICollectionViewLayoutAttributes *pose = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
    if (<test for incorrect frame>) {
        CGRect frame = pose.frame;
        frame.origin.y = <calculate correct frame>;
        pose.frame = frame;
    }
    return pose;
}

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

Обобщая немного, я считаю, что там UICollectionViewFlowLayout настолько глючит, и есть так много угловых случаев, с которыми можно бороться, если у вас есть элементы, перемещающиеся и выходящие из экрана, в сочетании с любыми вставками, удалениями или перемещениями, что мне было проще свернуть свои собственные простые макеты. Если вы не собираетесь делать какие-либо вставки, удаления или перемещения, то переопределение UICollectionViewFlowLayout вполне может быть вашим лучшим выбором.

Сообщите мне, если вам нужна дополнительная помощь.

ИЗМЕНИТЬ

Если вам интересно взглянуть на 3-й партийный макет, я открою исходный макет моей таблицы VCollectionViewGridLayout и добавил пример проекта демонстрируя гладкую расширяющуюся высоту ячейки. Попробуйте запустить Expand project. Существует также "Сортировка и фильтр" с анимированной сортировкой и фильтрацией. Оба проекта позволяют вам переключаться между раскладкой и сеткой, чтобы вы могли видеть улучшение.