10

UICollectionViewを使用して、iPhoneアプリ(iOS6)で画像のグリッドを表示しています。

UICollectionViewに垂直スクロールを使用していますが、画像はすべて固定幅でさまざまな高さです。画像の幅は、iPhoneで3列の画像が表示されるように設定されています。これは問題なく機能し、画像はグリッドビューで表示されます。

ただし、私の画像の高さはさまざまであるため、次の画像(HTMLで作成されたモックアップ)に示すように、列内の画像間の垂直方向の間隔が異なり、見栄えがよくありません。

画像が現在どのように配置されているかを示す画像

代わりに、列内の画像間の垂直方向の間隔が同じである、より流動的な流れを実現したいと思います。次のモックアップは、どのように機能させたいかを示しています。

画像の流れをどのように機能させたいかの例

これを解決する方法のアイデアはありますか?

また、おまけの質問として、アプリがiOS6用に構築されていない場合に同じ問題を解決する方法を知っている人はいますか(UICollectionViewはiOS6でのみ利用可能であるため)。サードパーティのコンポーネントを使用するか、標準のiOSコントロールで解決します。

4

2 に答える 2

9

サブクラスUICollectionViewFlowLayoutとそのクラスに、これらのメソッドを追加します。(これは垂直方向を想定しており、最初の行をスキップし、それらの間は一定の10ピクセルであることに注意してください。水平バージョンが必要な場合は、UICollectionViewflowLayoutのセル間の間隔をどのように決定するかを参照してください。

- (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 に答える