私は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 ]
私は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 ]
私はこのようなことをしなければなりませんでしたが、1 つのセクションにすべてのセルが必要でした。UICollectionViewFlowLayout
中央のセルに拡張するのは非常に簡単でした。私はポッドを作りました:
https://github.com/keighl/KTCenterFlowLayout
最初に少し背景を説明します。 a は、セルがビューに配置される方法を決定するUICollectionView
a と組み合わされます。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 のセルを中央揃えにする方法は? - はめ込み方法について詳しく説明しますが、あなたと同じことをしようとしているわけではありません。
サブクラス化しました -ここUICollectionViewFlowLayout
で見つけたコードを左揃えのコレクション ビューに変更しました。
次のようになります。
- (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;
}
それが誰かを助けることを願っています:)
これは、 からサブクラス化された (比較的) シンプルなカスタム レイアウトで実現できます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(¤tRowAttributes, 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(¤tRowAttributes, 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
}
}
}