Search code examples
iosobjective-cparallaxuiviewanimationuicollectionviewlayout

Ultravisual iOS application like animation using UICollectionViewLayout without overlapping of images


I have created the same component which currently available in UltraVisual iOS application for viewing the records in animation like parallax effects. Please find the below attached GIF image for more information. I want the same animation as in given video URL.

For that I had found the two GitHub URL which is almost same but it does not meet the same animation which used in the UltraVisual iOS application. For more information please find the below two url for the same.

URL : https://github.com/fdzsergio/SFFocusViewLayout/tree/2.0.0
URL : https://github.com/RobotsAndPencils/RPSlidingMenu

Problem :
Right now I am facing the issue of how to shrink the focused image considering the bottom part which remain static. First focused image should shrink from top (bottom part remain static) and at the same time next image will become focused considering the top of second image which remain static.

Current Code :

- (void)prepareLayout {

NSMutableArray *cache = [NSMutableArray array];

NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];

// last rect will be used to calculate frames past the first one.  We initialize it to a non junk 0 value
CGRect frame = CGRectZero;
CGFloat y = 0;
CGFloat footerTop = 0;

for (NSUInteger item = 0; item < numberOfItems; item++) {
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:0];
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]
    ;
    // Important because each cell has to slide over the top of the previous one
    attributes.zIndex = item;

    // Initially set the height of the cell to the standard height
    CGFloat height = self.standardHeight;

    if (indexPath.item == self.currentFocusedItemIndex) {
        // The featured cell
        CGFloat yOffset = self.standardHeight * self.nextItemPercentageOffset;
        y = self.collectionView.contentOffset.y - yOffset;
        //y = yOffset - self.standardHeight * self.nextItemPercentageOffset;

        height = self.focusedHeight;

        //*********CURRENTLY WORKING ON THIS LINE TO ACHIEVE THE REQUIRED ANIMATION ******************
        //attributes.transform = CGAffineTransformTranslate(attributes.transform, 0, -self.collectionView.contentOffset.y+self.dragOffset); //Solution might be here…

    } else if (indexPath.item == (self.currentFocusedItemIndex + 1) && indexPath.item != numberOfItems) {

        // The cell directly below the featured cell, which grows as the user scrolls
        CGFloat maxY = y + self.standardHeight;
        height =  self.standardHeight + MAX((self.focusedHeight - self.standardHeight) * self.nextItemPercentageOffset, 0);
        y = maxY - height;
       //attributes.transform = CGAffineTransformTranslate(attributes.transform, 0, -self.collectionView.contentOffset.y+self.dragOffset); 
    } else {
        y = frame.origin.y + frame.size.height;
       //attributes.transform = CGAffineTransformTranslate(attributes.transform, 0, -self.collectionView.contentOffset.y+self.dragOffset); 
    }

    frame = CGRectMake(0, y, self.collectionView.frame.size.width, height);
    attributes.frame = frame;

    [cache addObject:attributes];
    y = CGRectGetMaxY(frame);

    if (item == numberOfItems-1) {
        footerTop = CGRectGetMaxY(frame);
    }
};

for (NSUInteger item = 0; item < numberOfItems; item++) {
    if (item == 0) {
        footerTop = footerTop + self.focusedHeight;
    } else {
        footerTop = footerTop + self.standardHeight;
    }
}

CGSize footerSize = [self footerReferenceSizeInSection:0];
if (footerSize.height > 0) {
    UICollectionViewLayoutAttributes *footerAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
    footerAttributes.zIndex = 0;
    footerAttributes.frame = CGRectMake(0, footerTop, footerSize.width, footerSize.height);
    self.footerAttributes[0] = footerAttributes;
}
self.cachedLayoutAttributes = [cache copy];
}

I had changed the existing code of (https://github.com/fdzsergio/SFFocusViewLayout/tree/2.0.0) SFFocusLayout library and here is the code on which I made changes so far. For that I had mentioned the comment in code where I feel solution lies but unable to succeed as I am struggling it from last 3 to 4 days.

Please help me and thanks in advance.

Required animation with gif file


Solution

  • If you want to achieve animation like UltraVisual app. I modified prepareLayout Method in RPSlidingMenu.

    Below are changes need to in prepareLayout Method in file RPSlidingMenuLayout.m

    Need to change for first cell frame :

    if (indexPath.row == topFeatureIndex) 
    {
        // our top feature cell
        CGFloat yOffset = normalHeight  * topCellsInterpolation;
        yValue = self.collectionView.contentOffset.y - yOffset;
        CGFloat amountToGrow = MAX(featureHeight * topCellsInterpolation, 0);
        attributes.frame = CGRectMake(0.0f, self.collectionView.contentOffset.y -amountToGrow , screenWidth, featureHeight);
    }
    

    For Second cell but Not for last cell :

    else if (indexPath.row == (topFeatureIndex + 1) && indexPath.row != numItems)
    {
            yValue = lastRect.origin.y + lastRect.size.height;
            CGFloat amountToGrow = MAX((featureHeight - normalHeight) *topCellsInterpolation, 0);
            CGFloat bottomYValue = yValue + normalHeight + amountToGrow;
            NSInteger newHeight = normalHeight + amountToGrow;
            attributes.frame = CGRectMake(0.0f, 0.0f , screenWidth, screenWidth);
    }
    

    No Need to change for all other cell frames..

    You can see the animation in attached gif.

    Animation may look like you want !!!

    Hope it will help you...