UICollectionView horizontal scrolling, deleting last item, animation not working

前端 未结 6 427
我在风中等你
我在风中等你 2021-02-02 00:53

I have a UICollectionView. It scrolls horizontally, has only a single row of items, and behaves like a paging UIScrollView. I\'m making something along the lines of the Safari t

6条回答
  •  梦如初夏
    2021-02-02 01:05

    And here's yet another solution (targetIndexPath is the indexPath of the cell to be removed). This code can simply be placed in a removeCellAtIndexPath:(NSIndexPath*)targetIndexPath method and you're done (assuming my adaptations from my code to public code are correct, otherwise ask me and I'll try to help).

    // (Here it's assumed that self.collectionView.collectionViewLayout has been assigned a UICollectionViewFlowLayout before; note the word "FLOW" in that class name) 
    UICollectionViewFlowLayout* layout = (UICollectionViewFlowLayout*) self.collectionView.collectionViewLayout;
    
    // Find index path of the last cell in collection view:
    NSIndexPath* lastIndexPath = [self lastItemIndexPath];
    
    // Extend content area temporarily to fill out space left by the last row after deletion, if last row is visible:
    BOOL lastRowWasVisible = NO;
    if ([self.collectionView icn_cellAtIndexPathIsVisible:lastIndexPath]) {
    
        lastRowWasVisible = YES;
    
        // Adapt section spacing to temporarily fill out the space potentially left after removing last cell:
        CGFloat cellWithLineSpacingHeight = 79.0f + 8.0f; // Height of my cell + one line spacing
        layout.sectionInset = UIEdgeInsetsMake(0.0f, 0.0f, cellWithLineSpacingHeight, 0.0f);
    }
    
    // Remove the cell:
    [self.collectionView performBatchUpdates:^{
    
        [self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:targetIndexPath]];
    
    } completion:^(BOOL finished) {
    
        // Only scroll if we had the last row visible:
        if (lastRowWasVisible) {
    
            NSIndexPath* lastItemIndexPath = [self lastItemIndexPath];
    
            // Run a custom scroll animation for two reasons; 1. that way we can reset the insets when animation is finished, and 2. using the "animated:YES" option lags here for some reason:
            [UIView animateWithDuration:0.3f animations:^{
                [self.collectionView scrollToItemAtIndexPath:prevItemIndexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:NO];
            } completion:^(BOOL finished) {
    
                // Reset the space placeholder once having scrolled away from it:
                layout.sectionInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
            }];
        }
    }];
    

    The icn_cellAtIndexPathIsVisible: method is just a category on UICollectionView:

    - (BOOL) icn_cellAtIndexPathIsVisible:(NSIndexPath*)indexPath {
    
        BOOL __block wasVisible = NO;
        [self.indexPathsForVisibleItems enumerateObjectsUsingBlock:^(NSIndexPath* ip, NSUInteger idx, BOOL *stop) {
    
            if ([ip isEqual:indexPath]) {
    
                wasVisible = YES;
                *stop = YES;
            }
        }];
    
        return wasVisible;
    }
    

    Update: This only works with one section.

提交回复
热议问题