10

我正在使用 UICollectionView 在 iPhone 应用程序 (iOS6) 中呈现图像网格。

我正在为 UICollectionView 使用垂直滚动,并且图像都有固定的宽度和不同的高度。图像的宽度设置为在 iPhone 上显示 3 列图像。这工作正常,我得到了网格视图中显示的图像。

但是,由于我的图像具有不同的高度,因此列中图像之间的垂直间距会发生变化,这看起来不太好,如下图所示(用 HTML 制作的模型):

显示图像当前布局方式的图像

相反,我希望实现更流畅的流动,其中一列中图像之间的垂直间距相同。以下模型显示了我希望它如何工作:

我希望图像流如何工作的示例

关于如何解决这个问题的任何想法?

此外,作为奖励问题,如果应用程序不是为 iOS6 构建的(因为 UICollectionView 仅在 iOS6 中可用),是否有人知道解决相同问题的方法。通过使用 3rd 方组件或使用标准 iOS 控件解决它。

4

2 回答 2

9

子类 UICollectionViewFlowLayout 并在该类中添加这些方法。(请注意,这假定垂直方向,它会跳过第一行,并且它们之间是恒定的 10 个像素。请参阅:如果需要水平版本,如何确定 UICollectionView flowLayout 中的单元格之间的间距

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray* arr = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* atts in arr) {
    if (nil == atts.representedElementKind) {
        NSIndexPath* ip = atts.indexPath;
        atts.frame = [self layoutAttributesForItemAtIndexPath:ip].frame;
    }
}
return arr;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* atts =
[super layoutAttributesForItemAtIndexPath:indexPath];

if (indexPath.item == 0 || indexPath.item == 1) // degenerate case 1, first item of section
    return atts;

NSIndexPath* ipPrev =
[NSIndexPath indexPathForItem:indexPath.item-2 inSection:indexPath.section];

CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
CGFloat rightPrev = fPrev.origin.y + fPrev.size.height + 10;
if (atts.frame.origin.y <= rightPrev) // degenerate case 2, first item of line
    return atts;

CGRect f = atts.frame;
f.origin.y = rightPrev;
atts.frame = f;
return atts;
}
于 2013-01-26T22:33:58.017 回答
5

对于 Swift 3,这段代码对我有用,包括第一行到顶部的空间......

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let arr = super.layoutAttributesForElements(in: rect)

    for atts:UICollectionViewLayoutAttributes in arr! {
        if nil == atts.representedElementKind {
            let ip = atts.indexPath
            atts.frame = (self.layoutAttributesForItem(at: ip)?.frame)!
        }
    }
    return arr
}

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
    let atts = super.layoutAttributesForItem(at: indexPath)

    if indexPath.item == 0 || indexPath.item == 1 {
        var frame = atts?.frame;
        frame?.origin.y = sectionInset.top;
        atts?.frame = frame!;
        return atts
    }

    let ipPrev = IndexPath(item: indexPath.item - 2, section: indexPath.section)

    let fPrev = self.layoutAttributesForItem(at: ipPrev)?.frame

    let rightPrev = (fPrev?.origin.y)! + (fPrev?.size.height)! + 10

    if (atts?.frame.origin.y)! <= rightPrev {
        return atts
    }

    var f = atts?.frame
    f?.origin.y = rightPrev
    atts?.frame = f!
    return atts
}
于 2016-12-20T11:35:52.397 回答