iOS 悬停瀑布流

2,155 阅读2分钟
前言

        之前需求做一个瀑布流,当时就想,哟,瀑布流诶,不是很难呀,于是激情满满的开始,然而最后告诉我需要一个带有悬停效果的瀑布流,一脸懵逼...,这篇文章说一下我踩中的坑。

正文

        首先,我们要做一个瀑布流,首选多半是使用UICollectionView的,而在iOS 9.0后,collection已经支持section悬停,只需要将sectionHeadersPinToVisibleBounds设置为true,就可实现section悬停。而正常的瀑布流,只需要重写layoutAttributesForElementsInRect方法;那么要如何实现悬停的瀑布流呢?

        要实现悬停瀑布流,创建一个继承于UICollectionViewLayout的类,然后进行重绘;然后在重写layoutAttributesForElementsInRect这个方法时,进行判定是否需要悬停、需要悬停的section,于layoutAttributesForItemAtIndexPath这个方法中计算排列item显示;

        当然还需要在shouldInvalidateLayoutForBoundsChange中,return YES。

例子

        贴一点代码,先贴为敬。这段主要用于计算item等显示frame。

//是否切换section
    //当前列高度
    __block CGFloat curColumnHeight = 0;
    //目标列下标
    __block NSUInteger targetColumnIndex = 0;
    if (indexPath.section > _curSection) {
        _curSection = indexPath.section;
        //取最大
        [self find:YES completion:^(NSUInteger index, CGFloat height) {
            
            curColumnHeight = height;
        }];
        //更换section后均从第0列开始布局
        targetColumnIndex = 0;
        //换section后的更新统一高度
//        curColumnHeight -= self.minimumRowSpace;
        for (NSInteger i = 0; i < _columnCountsPerRow; i++) {
            _maxHeightForColumns[i] = @(curColumnHeight);
        }
    }
    else {
        //取最小
        [self find:NO completion:^(NSUInteger index, CGFloat height) {
            
            curColumnHeight = height;
            targetColumnIndex = index;
        }];
    }
    //计算当前cell的frame X:左边距 + 目标列下标 *(目标列宽度 + 列间距)
    CGFloat cellX = self.edgeInsets.left + targetColumnIndex *(cellWidth + self.minimumColumnSpace);
    CGFloat cellY = curColumnHeight;
    if (cellY != self.edgeInsets.top || cellY != self.edgeInsets.bottom) {
        //当显示列总数小于或等于分割列数时
        if ([self.collectionView numberOfItemsInSection:indexPath.section] <= _columnCountsPerRow) {
            cellY += self.edgeInsets.bottom + self.edgeInsets.top;
        }
        else {
            //当显示行不为第一行时
            if (indexPath.row > _columnCountsPerRow - 1) {
                cellY += self.minimumRowSpace;
            }
            //当显示行为最后一行时
            else if (indexPath.row == [self.collectionView numberOfItemsInSection:indexPath.section] - 1) {
                cellY += self.edgeInsets.bottom;
            }
            else {
                cellY += self.edgeInsets.top;
            }
        }
    }
    else {}

后语

Demo就在文章中,找找就有了😂