UICollectionView Layout like SnapChat?

流过昼夜 提交于 2019-11-26 23:13:15
Larme

Based on a precedent answer adapted to your issue:

-(id)initWithSize:(CGSize)size
{
  self = [super init];
  if (self)
  {
      _unitSize = CGSizeMake(size.width/2,80);
      _cellLayouts = [[NSMutableDictionary alloc] init];
  }
  return self;
}
-(void)prepareLayout
{
    for (NSInteger aSection = 0; aSection < [[self collectionView] numberOfSections]; aSection++)
    {

        //Create Cells Frames
        for (NSInteger aRow = 0; aRow < [[self collectionView] numberOfItemsInSection:aSection]; aRow++)
        {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:aRow inSection:aSection];
            UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

            NSUInteger i = aRow%3;
            NSUInteger j = aRow/3;
            CGFloat offsetY = _unitSize.height*2*j;
            CGPoint xPoint;
            CGFloat height = 0;
            BOOL invert = NO;
            if (aRow%6 >= 3) //We need to invert Big cell and small cells => xPoint.x
            {
                invert = YES;
            }
            switch (i)
            {
                case 0:
                    xPoint = CGPointMake((invert?_unitSize.width:0), offsetY);
                    height = _unitSize.height;
                    break;
                case 1:
                    xPoint = CGPointMake((invert?_unitSize.width:0), offsetY+_unitSize.height);
                    height = _unitSize.height;
                    break;
                case 2:
                    xPoint = CGPointMake((invert?0:_unitSize.width), offsetY);
                    height = _unitSize.height*2;
                    break;
                default:
                    break;
            }

            CGRect frame = CGRectMake(xPoint.x, xPoint.y, _unitSize.width, height);
            [attributes setFrame:frame];
            [_cellLayouts setObject:attributes forKey:indexPath];
        }

    }
}

I set the height of unitSize to 80, but you can use the size of the screen if needed, like _unitSize = CGSizeMake(size.width/2,size.height/4.);.

That render:

Side note: It's up to you to adapt the logic, or do changes, the cell frames calculation may not be the "best looking piece of code".

UICollectionViewLayout like the SnapChat's stories Like


Swift 3.2 Code

import Foundation

import UIKit

class StoryTwoColumnsLayout : UICollectionViewLayout {
    fileprivate var cache = [IndexPath: UICollectionViewLayoutAttributes]()
    fileprivate var cellPadding: CGFloat = 4
    fileprivate var contentHeight: CGFloat = 0
    var oldBound: CGRect!
    let numberOfColumns:Int = 2
    var cellHeight:CGFloat = 255

    fileprivate var contentWidth: CGFloat {
        guard let collectionView = collectionView else {
            return 0
        }
        let insets = collectionView.contentInset
        return collectionView.bounds.width - (insets.left + insets.right)
    }

    override var collectionViewContentSize: CGSize {
        return CGSize(width: contentWidth, height: contentHeight)
    }

    override func prepare() {
        super.prepare()
        contentHeight = 0
        cache.removeAll(keepingCapacity: true)
        guard cache.isEmpty == true, let collectionView = collectionView else {
            return
        }
        if collectionView.numberOfSections == 0 {
            return
        }

        let cellWidth = contentWidth / CGFloat(numberOfColumns)
        cellHeight = cellWidth / 720 * 1220
        var xOffset = [CGFloat]()
        for column in 0 ..< numberOfColumns {
            xOffset.append(CGFloat(column) * cellWidth)
        }
        var column = 0
        var yOffset = [CGFloat](repeating: 0, count: numberOfColumns)

        for item in 0 ..< collectionView.numberOfItems(inSection: 0) {
            let indexPath = IndexPath(item: item, section: 0)
            var newheight = cellHeight
            if column == 0 {
             newheight = ((yOffset[column + 1] - yOffset[column]) > cellHeight * 0.3) ? cellHeight : (cellHeight * 0.90)
            }

            let frame = CGRect(x: xOffset[column], y: yOffset[column], width: cellWidth, height: newheight)
            let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = insetFrame
            cache[indexPath] = (attributes)
            contentHeight = max(contentHeight, frame.maxY)
            yOffset[column] = yOffset[column] + newheight
            if column >= (numberOfColumns - 1) {
                column = 0
            } else {
                column = column + 1
            }

        }
    }



    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
        // Loop through the cache and look for items in the rect
        visibleLayoutAttributes = cache.values.filter({ (attributes) -> Bool in
            return attributes.frame.intersects(rect)
        })
        print(visibleLayoutAttributes)
        return visibleLayoutAttributes
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        // print(cache[indexPath.item])
        return cache[indexPath]
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!