UICollectionView выполняетBatchUpdates: оживляет все разделы - программирование
Подтвердить что ты не робот

UICollectionView выполняетBatchUpdates: оживляет все разделы

Я пишу пользовательский UICollectionViewFlowLayout, и я заметил, что initialLayoutAttributesForAppearingItemAtIndexPath: и initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath: будут вызываться для всех разделов, когда я вызываю performBatchUpdates:completion: в виде коллекции. В результате все секции имеют анимацию, применяемую к ним, а не только добавленную секцию.

[collectionView performBatchUpdates:^{
    currentModelArrayIndex++;
    [collectionView insertSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex]];
    [collectionView reloadSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex-1]];
} completion:^(BOOL finished) {
    [collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:currentModelArrayIndex] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
}];

То, что я пробовал до сих пор, заключается в удалении вызова performBatchUpdates:completion: вместо простых обновлений, но уже существующие разделы (все они) анимированы в любом случае. Я придумал решение проверки, чтобы убедиться, что я изменяю атрибуты макета только в последнем разделе, но он чувствует себя взломанным.

if (decorationIndexPath.section == [(id<UICollectionViewDataSource>)self.collectionView.delegate numberOfSectionsInCollectionView:self.collectionView] - 1)
{
   layoutAttributes.alpha = 0.0f;
   layoutAttributes.transform3D = CATransform3DMakeTranslation(-CGRectGetWidth(layoutAttributes.frame), 0, 0);
}

Является ли это подходящим способом для анимации только некоторых разделов?

4b9b3361

Ответ 1

Хорошо, у меня есть ответ; он не намного красивее предыдущего, но он держит макет от касания источника данных, поэтому он чище.

В принципе, нам нужно переопределить prepareForCollectionViewUpdates: и finalizeCollectionViewUpdates, чтобы отслеживать разделы, которые мы вставляем. У меня есть изменяемый набор, содержащий NSNumber экземпляры разделов, которые мы вставляем.

-(void)prepareForCollectionViewUpdates:(NSArray *)updateItems
{
    [super prepareForCollectionViewUpdates:updateItems];

    [updateItems enumerateObjectsUsingBlock:^(UICollectionViewUpdateItem *updateItem, NSUInteger idx, BOOL *stop) {
        if (updateItem.updateAction == UICollectionUpdateActionInsert)
        {
            [insertedSectionSet addObject:@(updateItem.indexPathAfterUpdate.section)];
        }
    }];
}

-(void)finalizeCollectionViewUpdates
{
    [super finalizeCollectionViewUpdates];

    [insertedSectionSet removeAllObjects];
}

Далее, я проверяю, включен ли раздел указателя пути в этот набор при установке начальных атрибутов макета для элементов и видов оформления.

-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath
{
    UICollectionViewLayoutAttributes *layoutAttributes;

    if ([elementKind isEqualToString:AFCollectionViewFlowLayoutBackgroundDecoration])
    {
        if ([insertedSectionSet containsObject:@(decorationIndexPath.section)])
        {
            layoutAttributes = [self layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:decorationIndexPath];
            layoutAttributes.alpha = 0.0f;
            layoutAttributes.transform3D = CATransform3DMakeTranslation(-CGRectGetWidth(layoutAttributes.frame), 0, 0);
        }
    }

    return layoutAttributes;
}

-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
    UICollectionViewLayoutAttributes *layoutAttributes;

    if ([insertedSectionSet containsObject:@(itemIndexPath.section)])
    {
        layoutAttributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
        layoutAttributes.transform3D = CATransform3DMakeTranslation([self collectionViewContentSize].width, 0, 0);
    }

    return layoutAttributes;
}

Я возвращаю nil из этих методов иначе, потому что значение nil является значением по умолчанию.

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