UICollectionView insert cells above maintaining position (like Messages.app)

后端 未结 20 2038
渐次进展
渐次进展 2020-12-02 07:23

By default Collection View maintains content offset while inserting cells. On the other hand I\'d like to insert cells above the currently displaying ones so that they appea

20条回答
  •  遥遥无期
    2020-12-02 08:00

    Not the most elegant but quite simple and working solution I stuck with for now. Works only with linear layout (not grid) but it's fine for me.

    // retrieve data to be inserted
    NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:nil];
    NSMutableArray *objects = [fetchedObjects mutableCopy];
    [objects addObjectsFromArray:self.messages];
    
    // self.messages is a DataSource array
    self.messages = objects;
    
    // calculate index paths to be updated (we are inserting 
    // fetchedObjects.count of objects at the top of collection view)
    NSMutableArray *indexPaths = [NSMutableArray new];
    for (int i = 0; i < fetchedObjects.count; i ++) {
        [indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:0]];
    }
    
    // calculate offset of the top of the displayed content from the bottom of contentSize
    CGFloat bottomOffset = self.collectionView.contentSize.height - self.collectionView.contentOffset.y;
    
    // performWithoutAnimation: cancels default collection view insertion animation
    [UIView performWithoutAnimation:^{
    
        // capture collection view image representation into UIImage
        UIGraphicsBeginImageContextWithOptions(self.collectionView.bounds.size, NO, 0);
        [self.collectionView drawViewHierarchyInRect:self.collectionView.bounds afterScreenUpdates:YES];
        UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        // place the captured image into image view laying atop of collection view
        self.snapshot.image = snapshotImage;
        self.snapshot.hidden = NO;
    
        [self.collectionView performBatchUpdates:^{
            // perform the actual insertion of new cells
            [self.collectionView insertItemsAtIndexPaths:indexPaths];
        } completion:^(BOOL finished) {
            // after insertion finishes, scroll the collection so that content position is not
            // changed compared to such prior to the update
            self.collectionView.contentOffset = CGPointMake(0, self.collectionView.contentSize.height - bottomOffset);
            [self.collectionView.collectionViewLayout invalidateLayout];
    
            // and hide the snapshot view
            self.snapshot.hidden = YES;
        }];
    }];
    

提交回复
热议问题