4

I would like to add and sync the rotation transition effect while scrolling through the collection view, so far I managed to complete the following by resizing, add fading effect & snapping of the collection view cell when it's near to the center of the scroll view.

The expected result should be like this:

enter image description here

Effect of fading the collection view while scrolling:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    
    // When the cell is at the center it has it's the original size
    // When the cell is moving left | right make it smaller by multiplying its size with a smaller scale
    // The scale is determined by the distance from the center of the cell to the center of the collection view

    let centerX = collectionView.center.x

    for (index, cell) in collectionView.visibleCells.enumerated()  {
        // Coordinate of the cell in the viewcontroller's root view coordinate space
        let cell = cell as! PlayerMixerCollectionCell
        let basePosition = cell.convert(CGPoint.zero, to: self.view)
        let cellCenterX = basePosition.x + collectionView.frame.size.height / 2.0
        let tolerance = 0.02

        let distance = abs(cellCenterX - centerX)
        var scale = 1.0 + tolerance - (Double(( distance / centerX )) * 0.105)
        
        // Set maximum scale for centered item
        if (scale > 1.0) {
            scale = 1.0
        }

        // Set minimum scale so the previous and next item will have the same size
        if (scale < 0.860091) {
            scale = 0.860091
        }
        
        if (scale > 0.860091 && scale < 1.0) {
            // Transform the previous and next item cell size based on the scale
            cell.setItemAsInactive(withScale: CGFloat(scale))
        } else {
            // Transform the centered item cell size based on the scale
            cell.setItemAsActive(withScale: CGFloat(scale))
        }
    }
}

Snapping to the nearest collection view cell and position it at the center:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    // Stop scrolling to this point
    targetContentOffset.pointee = collectionView.contentOffset

    // Calculate conditions
    let indexOfMajorItem = determineIndexOfMajorItem()
    let itemCount = cells.count - 1

    let swipeVelocityThreshold: CGFloat = 0.5
    let hasEnoughVelocityToSlideToNextItem = indexOfCellBeforeDragging + 1 < itemCount && velocity.x > swipeVelocityThreshold
    let hasEnoughVelocityToSlideToPrevItem = indexOfCellBeforeDragging - 1 >= 0 && velocity.x < -swipeVelocityThreshold

    let isMajorItemMatchPrevItem = indexOfMajorItem == indexOfCellBeforeDragging
    let didSwipeToSkipItem = isMajorItemMatchPrevItem && (hasEnoughVelocityToSlideToNextItem || hasEnoughVelocityToSlideToPrevItem)

    // If possible animate so that swipe animation continues or pop back to the expected item
    let snappedItemIndex = didSwipeToSkipItem ? indexOfCellBeforeDragging + (hasEnoughVelocityToSlideToNextItem ? 1 : -1) : indexOfMajorItem
    let snappedItemIndexPath = IndexPath(item: snappedItemIndex, section: 0)
    
    indexOfCenteredCell = snappedItemIndexPath
    
    // Scroll to the snapped item
    collectionView.scrollToItem(at: snappedItemIndexPath, at: .centeredHorizontally, animated: true)
}
Sharkes Monken
  • 661
  • 5
  • 23

0 Answers0