Delete a cell on the edge of a UICollectionView - cells that do not appear immediately after scrolling

Consider a standard, vertically scrollable flow layout filled with enough cells to trigger scrolling. When scrolling down, if you delete an element in such a way that the size of the contents of the collection view should be reduced to accommodate a new number of elements (i.e., delete the last element in the bottom row), the row of cells that scroll from the top are hidden. At the end of the delete animation, the top line appears without animation - this is a very unpleasant effect.

In slow motion:

Cells not appearing

It is very simple to reproduce:

  • Create a new project with one view and change the default value ViewControlleras a subclassUICollectionViewController

  • UICollectionViewController , , ViewController. "" 200x200.

  • ViewController.m:


@interface ViewController ()
@property(nonatomic, assign) NSInteger numberOfItems;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.numberOfItems = 19;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.numberOfItems;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    self.numberOfItems--;
    [collectionView deleteItemsAtIndexPaths:@[indexPath]];
}

@end



, , , . UICollectionView, , - , . cell.hidden = NO (hidden - YES). hidden, , , , .

-initialLayoutAttributesForAppearingItemAtIndexPath , deleteItemsAtIndexPaths:, , . , , reloadData , , , , :

[collectionView deleteItemsAtIndexPaths:@[indexPath]];
[collectionView performBatchUpdates:^{
    [collectionView reloadData];
} completion:nil];

, , . , , reloadData - , .



:

, , . , , layoutSubviews, (layoutAttributesForElementsInRect:) applyLayoutAttributes: .

:

// user taps cell (to delete it)
-deleteItemsAtIndexPaths:
-layoutAttributesForElementsInRect:
-finalLayoutAttributes...:                // Called for the item being deleted
-finalLayoutAttributes...:                // \__ Called for each index path visible
-initialLayoutAttributes...:              // /   when deletion started
-applyLayoutAttributes:                   // Called for the item being deleted, to apply final layout attributes
// collection view begins scrolling up
-layoutSubviews:                          // Called multiple times as the 
-layoutAttributesForElementsInRect:       // collection view scrolls
// ... for any new set of
// ... attributes returned:
-collectionView:cellForItemAtIndexPath:
-applyLayoutAttributes:                   // Sets the standard attributes for the new cell
// collection view finishes scrolling

; , . , collectionView:cellForItemAtIndexPath: applyLayoutAttributes: , , ( hidden = NO).

, , , , , . UICollectionView, layoutSubviews, : _updateVisibleCellsNow:. , , , , , , .


, , , , , , /. , :

- (void)addCell
{
    NSIndexPath *indexPathToInsert = [NSIndexPath indexPathForItem:self.numberOfItems
                                                         inSection:0];
    self.numberOfItems++;
    [self.collectionView insertItemsAtIndexPaths:@[indexPathToInsert]];
    [self.collectionView scrollToItemAtIndexPath:indexPathToInsert
                                atScrollPosition:UICollectionViewScrollPositionCenteredVertically
                                        animated:YES];
}

, , , , .

iOS 7 iOS 8 beta 5.

+6
1

, .

collectionView.contentInsets = UIEdgeInsetsMake(-5,0,0,0); //Adjust this value until it looks ok
0

All Articles