前言
之前需求做一个瀑布流,当时就想,哟,瀑布流诶,不是很难呀,于是激情满满的开始,然而最后告诉我需要一个带有悬停效果的瀑布流,一脸懵逼...,这篇文章说一下我踩中的坑。
正文
首先,我们要做一个瀑布流,首选多半是使用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就在文章中,找找就有了😂