43

私はUICollectionViewランダムなセルを持っています。行を中央に配置できる方法はありますか?

これは、デフォルトでどのように見えるかです:

[ x x x x x x ]  
[ x x x x x x ]  
[ x x         ]  

目的のレイアウトは次のようになります。

[ x x x x x ]  
[ x x x x x ]  
[    x x    ]  
4

9 に答える 9

46

私はこのようなことをしなければなりませんでしたが、1 つのセクションにすべてのセルが必要でした。UICollectionViewFlowLayout中央のセルに拡張するのは非常に簡単でした。私はポッドを作りました:

https://github.com/keighl/KTCenterFlowLayout

ここに画像の説明を入力

于 2014-10-09T20:20:58.237 に答える
23

最初に少し背景を説明します。 a は、セルがビューに配置される方法を決定するUICollectionViewa と組み合わされます。UICollectionViewLayoutこれは、コレクション ビューが非常に柔軟であることを意味します (コレクション ビューを使用してほとんどすべてのレイアウトを作成できます) が、レイアウトの変更が少し混乱する可能性があることも意味します。

まったく新しいレイアウト クラスを作成するのは複雑なので、代わりに、デフォルトのレイアウト ( UICollectionViewFlowLayout) を変更して中央揃えにすることをお勧めします。さらに単純にするために、おそらくフロー レイアウト自体をサブクラス化することは避けたいでしょう。

これが1つのアプローチです(これは最良のアプローチではないかもしれませんが、私が考えることができる最初のアプローチです)-次のように、セルを2つのセクションに分割します。

[ x x x x x ] <-- Section 1 
[ x x x x x ] <-- Section 1 
[    x x    ] <-- Section 2 

スクロール ビューの幅と各行に収まるセルの数がわかっている場合、これはかなり簡単です。

次に、collectionView:layout:insetForSectionAtIndex:デリゲート メソッドを使用して、2 番目のセクションの余白を設定し、垂直方向の中央に表示されるようにします。これが完了したら、縦向きと横向きの両方をサポートできるように、適切なセクション分割/インセットを再計算する必要があります。

ここに似たような質問があります - UICollectionView のセルを中央揃えにする方法は? - はめ込み方法について詳しく説明しますが、あなたと同じことをしようとしているわけではありません。

于 2013-05-14T13:54:07.540 に答える
2

サブクラス化しました -ここUICollectionViewFlowLayoutで見つけたコードを左揃えのコレクション ビューに変更しました。

  1. コレクション ビューを左揃えにします
  2. ライン配列の属性をグループ化する
  3. 各行について:
    • 右側のスペースを計算する
    • 行の各属性にスペースの半分を追加します

次のようになります。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

    NSArray *attributesForElementsInRect = [super layoutAttributesForElementsInRect:rect];
    NSMutableArray *newAttributesForElementsInRect = [[NSMutableArray alloc] initWithCapacity:attributesForElementsInRect.count];

    CGFloat leftMargin = self.sectionInset.left;
    NSMutableArray *lines = [NSMutableArray array];
    NSMutableArray *currLine = [NSMutableArray array];

    for (UICollectionViewLayoutAttributes *attributes in attributesForElementsInRect) {
        // Handle new line
        BOOL newLine = attributes.frame.origin.x <= leftMargin;
        if (newLine) {
            leftMargin = self.sectionInset.left; //will add outside loop
            currLine = [NSMutableArray arrayWithObject:attributes];
        } else {
            [currLine addObject:attributes];
        }

        if ([lines indexOfObject:currLine] == NSNotFound) {
            [lines addObject:currLine];
        }

        // Align to the left
        CGRect newLeftAlignedFrame = attributes.frame;
        newLeftAlignedFrame.origin.x = leftMargin;
        attributes.frame = newLeftAlignedFrame;

        leftMargin += attributes.frame.size.width + self.minimumInteritemSpacing;
        [newAttributesForElementsInRect addObject:attributes];
    }

    // Center left aligned lines
    for (NSArray *line in lines) {
        UICollectionViewLayoutAttributes *lastAttributes = line.lastObject;
        CGFloat space = CGRectGetWidth(self.collectionView.frame) - CGRectGetMaxX(lastAttributes.frame);

        for (UICollectionViewLayoutAttributes *attributes in line) {
            CGRect newFrame = attributes.frame;
            newFrame.origin.x = newFrame.origin.x + space / 2;
            attributes.frame = newFrame;

        }
    }

    return newAttributesForElementsInRect;
}

それが誰かを助けることを願っています:)

于 2016-05-29T14:56:55.927 に答える
2

これは、 からサブクラス化された (比較的) シンプルなカスタム レイアウトで実現できますUICollectionViewFlowLayout。の例を次に示しSwiftます。

/**
 * A simple `UICollectionViewFlowLayout` subclass that would make sure the items are center-aligned in the collection view, when scrolling vertically.
 */
class UICollectionViewFlowCenterLayout: UICollectionViewFlowLayout {

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let suggestedAttributes = super.layoutAttributesForElementsInRect(rect) else { return nil }

        guard scrollDirection == .Vertical else { return suggestedAttributes }

        var newAttributes: [UICollectionViewLayoutAttributes] = []

        /// We will collect items for each row in this array
        var currentRowAttributes: [UICollectionViewLayoutAttributes] = []
        /// We will use this variable to detect new rows when iterating over items
        var yOffset:CGFloat = sectionInset.top
        for attributes in suggestedAttributes {
            /// If we happen to run into a new row...
            if attributes.frame.origin.y != yOffset {
                /*
                 * Update layout of all items in the previous row and add them to the resulting array
                 */
                centerSingleRowWithItemsAttributes(&currentRowAttributes, rect: rect)
                newAttributes += currentRowAttributes
                /*
                 * Reset the accumulated values for the new row
                 */
                currentRowAttributes = []
                yOffset = attributes.frame.origin.y
            }
            currentRowAttributes += [attributes]
        }
        /*
         * Update the layout of the last row.
         */
        centerSingleRowWithItemsAttributes(&currentRowAttributes, rect: rect)
        newAttributes += currentRowAttributes

        return newAttributes
    }

    /**
     Updates the attributes for items, so that they are center-aligned in the given rect.

     - parameter attributes: Attributes of the items
     - parameter rect:       Bounding rect
     */
    private func centerSingleRowWithItemsAttributes(inout attributes: [UICollectionViewLayoutAttributes], rect: CGRect) {
        guard let item = attributes.last else { return }

        let itemsCount = CGFloat(attributes.count)
        let sideInsets = rect.width - (item.frame.width * itemsCount) - (minimumInteritemSpacing * (itemsCount - 1))
        var leftOffset = sideInsets / 2

        for attribute in attributes {
            attribute.frame.origin.x = leftOffset
            leftOffset += attribute.frame.width + minimumInteritemSpacing
        }
    }
}
于 2016-05-15T13:10:47.123 に答える