UICollectionViewセルを水平方向に中央揃えする方法は?


123

いくつかの調査を行いましたが、UICollectionViewのセルを水平方向に中央揃えする方法のコード例を見つけることができませんでした。

最初のセルがこのX00のようになる代わりに、この0X0のようにしたいのです。これを達成する方法はありますか?

編集:

私が欲しいものを視覚化する:

ここに画像の説明を入力してください

CollectionViewに要素が1つしかない場合は、バージョンBのようにする必要があります。複数の要素を取得すると、バージョンAのようになりますが、要素が多くなります。

現時点では、要素が1つしかない場合はバージョンAのように見えますが、どうすればBのように見せることができるのでしょうか。

助けてくれてありがとう!


セルをコレクションビューの幅に合わせてから、コレクションビュー自体をその親の中央に配置する方が簡単ではないですか。
Arthur Gevorkyan

はい、これを行うには少なくとも2つの方法があります。最初に(高速)は、画面全体のセル幅を作成し、その子ビューを中央に配置します。2番目(右)カスタムコレクションビューレイアウトを実装
sage444

最終的にバックエンドからのセルが増えるため、幅全体を埋めるのは良い考えではありません
RaptoX

幅を広げて中央に設定するのに十分です
Kishore Kumar

回答:


227

ライブラリの使用目的がこれだけの場合、つまり中央揃えにする場合は、ライブラリを使用することはお勧めしません。

この単純な計算は、collectionViewLayout関数で行う方がよいでしょう。

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    let totalCellWidth = CellWidth * CellCount
    let totalSpacingWidth = CellSpacing * (CellCount - 1)

    let leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}

2
@DarshanPatel。これを実装した多くの回答に感謝し、行は中央に表示されるはずですが、問題は最初のアイテムにスクロールできないことです。最初のアイテムにスクロールしようとすると、変更されたUIEdgeInsetsに戻ります。私のデモアプリgithub.com/anirudha-music/CollectionViewCenter
Anirudha Mahale

5
Swift 3では、新しいメソッドシグネチャはcollectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int)です。
カムチャッカ2017年

1
どのようにcellWidthを取得できますか?cellForItemAtメソッドを使用して可能ですか?試してみたところ、nilが返されました。セルサイズは、画面サイズに基づいて変化します。@ DarshanPatel。
Chris

10
@DarshanPatel。小さいデバイスでは、答えがマイナスの値になる場合があります。あなたに最大のチェックを使用することを検討してくださいleftInset:そうのような値let leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
Rhuariグレン

3
UICollectionViewControllerをサブクラス化していない場合は、クラスがUICollectionViewDelegateFlowLayoutに準拠していることを確認してください。準拠していない場合は機能しません
Saeed Ir

59

Swift 5.1

func centerItemsInCollectionView(cellWidth: Double, numberOfItems: Double, spaceBetweenCell: Double, collectionView: UICollectionView) -> UIEdgeInsets {
    let totalWidth = cellWidth * numberOfItems
    let totalSpacingWidth = spaceBetweenCell * (numberOfItems - 1)
    let leftInset = (collectionView.frame.width - CGFloat(totalWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset
    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}

Swift 4.2

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

    let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
    let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)

    let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)

}

スウィフト3

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

        let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
        let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)

        let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
        let rightInset = leftInset

        return UIEdgeInsetsMake(0, leftInset, 0, rightInset)

    }

プロトコルを追加することを忘れないでください

UICollectionViewDelegateFlowLayout

おそらく@ashForIosの制約
Ahmed Safadi 2018年

セル数が増加したときにcollectionViewに適合するセルがあり、セルが中央にあり、最初のセルまたは最後にスクロールできない場合、あなたの答えはうまくいきます。
NickCoder

2
@Vitalii 80はセルの幅を意味し、10はセル間のスペースを意味します。変数名を読むと、それが何を意味するか理解できます:P
Ahmed Safadi

Swift 4.2ソリューションの方が簡単です。ありがとうございます。「80」を実際のセルオブジェクトの幅に設定してください。
ジョンピッツ

25

これをSwift 4で試してください

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let cellWidth : CGFloat = 165.0

        let numberOfCells = floor(self.view.frame.size.width / cellWidth)
        let edgeInsets = (self.view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsetsMake(15, edgeInsets, 0, edgeInsets)
    }

代わりにcellWidthを追加してください165.0


1
これが最良の答えです。それに最も簡単な数学を。任意の数の行と列で動作します
rickrvo

20

私はこれにKTCenterFlowLayoutを使用します。UICollectionViewFlowLayout必要に応じてセルを中央に配置するカスタムサブクラスです。(注:これは、コードを投稿して解決するのは簡単なことではないため、GitHubプロジェクトにリンクしています!)


IBから機能させることができませんでした。このライブラリーは私にとって魅力的なものでした。ポッドをインストールして、IBのレイアウトのクラスを変更しました!
tagirkaZ

15

Darshan Patelの回答の客観的Cバージョン:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    CGFloat totalCellWidth = kItemWidth * self.dataArray.count;
    CGFloat totalSpacingWidth = kSpacing * (((float)self.dataArray.count - 1) < 0 ? 0 :self.dataArray.count - 1);
    CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
    CGFloat rightInset = leftInset;
    UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
    return sectionInset;
}

ありがとう。単一行で正常に機能します。しかし、複数行で問題を作成します。ここにスクリーンショットを表示するためのURLを追加できません。。ただし、小さなURLに「yynoalzg」を追加できます。あなたはアイデアを得ます。ゴールドセクションには4つのレコードがあります。4番目は改行する必要があります。。しかし、この方法の後、それはそのように表示されます...何かアイデアがあれば教えてください。
Hitarth

6

@Safad Funyの答えを少し変更すると、これがSwiftとiOSの最新バージョンで私にとってうまくいきました。この場合、セルの幅をコレクションビューのサイズの3分の1にする必要がありました。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

  let totalCellWidth = Int(collectionView.layer.frame.size.width) / 3 * collectionView.numberOfItems(inSection: 0)
  let totalSpacingWidth = (collectionView.numberOfItems(inSection: 0) - 1)

  let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
  let rightInset = leftInset

  return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

2
これは、特にセルが1つしかない場合に役立ちました。
Dasoga

6

この拡張機能を使用できます(Swift 4)。

あなたcollectionViewが持っている場合、それはセルを中央に置くことができますlayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize

どんなセルサイズでも機能し、 scrollDirection = .horizontal

public extension UICollectionView {
    func centerContentHorizontalyByInsetIfNeeded(minimumInset: UIEdgeInsets) {
        guard let layout = collectionViewLayout as? UICollectionViewFlowLayout,
            layout.scrollDirection == .horizontal else {
                assertionFailure("\(#function): layout.scrollDirection != .horizontal")
                return
        }

        if layout.collectionViewContentSize.width > frame.size.width {
            contentInset = minimumInset
        } else {
            contentInset = UIEdgeInsets(top: minimumInset.top,
                                        left: (frame.size.width - layout.collectionViewContentSize.width) / 2,
                                        bottom: minimumInset.bottom,
                                        right: 0)
        }
    }
}


final class Foo: UIViewController {
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        collectionView.centerContentHorizontalyByInsetIfNeeded(minimumInset: yourDefaultInset)
    }
}

お役に立てば幸いです。


1
エラーの取得:スレッド1:EXC_BAD_ACCESS(code = 2、address = 0x118ffde58)
atulkhatri

4

Swift 4.2(水平および垂直)。それはピンクパンサーコードの小さなアップグレードであり、彼に感謝します!


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellHieght: CGFloat = flowLayout.itemSize.height
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    var collectionHeight = collectionView.frame.size.height
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
        collectionHeight -= collectionView.safeAreaInsets.top + collectionView.safeAreaInsets.bottom
    }
    let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
    let totalHieght = cellHieght * cellCount + cellSpacing * (cellCount - 1)
    if totalWidth <= collectionWidth {
        let edgeInsetWidth = (collectionWidth - totalWidth) / 2

        print(edgeInsetWidth, edgeInsetWidth)
        return UIEdgeInsets(top: 5, left: edgeInsetWidth, bottom: flowLayout.sectionInset.top, right: edgeInsetWidth)
    } else {
        let edgeInsetHieght = (collectionHeight - totalHieght) / 2
        print(edgeInsetHieght, edgeInsetHieght)
        return UIEdgeInsets(top: edgeInsetHieght, left: flowLayout.sectionInset.top, bottom: edgeInsetHieght, right: flowLayout.sectionInset.top)

    }
}

クラスがUICollectionViewDelegateFlowLayoutプロトコルに準拠していることを確認してください


本当にあなたのコードは私にとって素晴らしい働きをします。デュードに感謝します。)
steveSarsawa

4

以下はSwift 5の新しいバージョンで、セルが複数行の場合にも正常に機能します。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    var cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    var totalWidth: CGFloat
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
    }
    repeat {
        totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
        cellCount -= 1
    } while totalWidth >= collectionWidth

    if (totalWidth > 0) {
        let edgeInset = (collectionWidth - totalWidth) / 2
        return UIEdgeInsets.init(top: flowLayout.sectionInset.top, left: edgeInset, bottom: flowLayout.sectionInset.bottom, right: edgeInset)
    } else {
        return flowLayout.sectionInset
    }
}

クラスがプロトコルに準拠していることを確認してくださいUICollectionViewDelegateFlowLayout


3

スウィフト4

extension ViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

        let cellWidth: CGFloat = 170.0 // Your cell width

        let numberOfCells = floor(view.frame.size.width / cellWidth)
        let edgeInsets = (view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets)
    }

 }

2

パディング上、左、下、右)のみを追加したい人向け):

プロトコルを追加する UICollectionViewDelegateFlowLayout

この例では、左右に40をパディングします。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {        
    return UIEdgeInsetsMake(0, 40, 0, 40)
}

2

SWIFT 4.2

private lazy var contentView: UICollectionView = {
        let layoutView: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layoutView.scrollDirection = .horizontal
            layoutView.minimumInteritemSpacing = 0
            layoutView.minimumLineSpacing = 5

        let collectionView: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: layoutView)
            collectionView.dataSource = self
            collectionView.delegate = self
            collectionView.showsHorizontalScrollIndicator = false
            collectionView.isPagingEnabled = true
            collectionView.registerCell(Cell.self)
            collectionView.backgroundColor = .clear
            collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

//

extension CustomCollectionView: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: collectionView.frame.width*4/5, height: collectionView.frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let cellWidth : CGFloat = collectionView.frame.width*4/5

        let numberOfCells = floor(collectionView.frame.width / cellWidth)
        let edgeInsets = (collectionView.frame.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsets(top: 0, left: edgeInsets, bottom: 0, right: edgeInsets)
    }
}

1

それがうまくいく私の解決策を試すことができます、

func refreshCollectionView(_ count: Int) {
    let collectionViewHeight = collectionView.bounds.height
    let collectionViewWidth = collectionView.bounds.width
    let numberOfItemsThatCanInCollectionView = Int(collectionViewWidth / collectionViewHeight)
    if numberOfItemsThatCanInCollectionView > count {
        let totalCellWidth = collectionViewHeight * CGFloat(count)
        let totalSpacingWidth: CGFloat = CGFloat(count) * (CGFloat(count) - 1)
        // leftInset, rightInset are the global variables which I am passing to the below function
        leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2;
        rightInset = -leftInset
    } else {
        leftInset = 0.0
        rightInset = -collectionViewHeight
    }
    collectionView.reloadData()
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

1

受け入れ答えは正解ですが、あなたがもしtotalCellWidth未満であるCollectionViewwidthが、ちょうどあなたが以下のように行うことができ、この防ぐために。

if (leftInset > 0) {
     return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
  } else {
     return UIEdgeInsetsMake(0, 10, 0, 10)
}

1

このコードは、Swift 4.0でも変更なしでコレクションビューを水平方向に中央揃えする必要があります。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
    }
    let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
    if totalWidth <= collectionWidth {
        let edgeInset = (collectionWidth - totalWidth) / 2
        return UIEdgeInsetsMake(flowLayout.sectionInset.top, edgeInset, flowLayout.sectionInset.bottom, edgeInset)
    } else {
        return flowLayout.sectionInset
    }
}

クラスがUICollectionViewDelegateFlowLayoutプロトコルに準拠していることを確認してください


0

私はここで、まったく異なるアプローチをとることになりました。

コレクションビューの制約を設定して、中央に水平に配置します。次に、幅を指定する別の制約を設定します。コレクションビューを保持するviewController内に幅制約のアウトレットを作成しました。次に、データソースが変更され、コレクションビューを更新しているときに、セルの数を取得し、(非常によく似た)計算を行って幅をリセットします。

let newWidth = (items.count * cellWidth) + (items.count * cellSpacing)

次に、制約アウトレットの .constant値を計算結果に設定し、残りはautolayoutが行います。

これは `UICollectionViewDelegateFlowLayoutと競合する可能性がありますが、これは、左揃えのコレクションビューを作成するために完全に機能しました。デリゲートがないと、セルがビューの大部分を占めたときにのみ機能するように見えます。


0

ページが幅より狭い場合はページを中央に配置し、それより多い場合は左揃えにするフローレイアウトの一般的なソリューション

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    // Centering if there are fever pages
    CGSize itemSize = [(UICollectionViewFlowLayout *)collectionViewLayout itemSize];
    CGFloat spacing = [(UICollectionViewFlowLayout *)collectionViewLayout minimumLineSpacing];

    NSInteger count = [self collectionView:self numberOfItemsInSection:section];
    CGFloat totalCellWidth = itemSize.width * count;
    CGFloat totalSpacingWidth = spacing * ((count - 1) < 0 ? 0 : count - 1);
    CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
    if (leftInset < 0) {
        UIEdgeInsets inset = [(UICollectionViewFlowLayout *)collectionViewLayout sectionInset];
        return inset;
    }
    CGFloat rightInset = leftInset;
    UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
    return sectionInset;
}

Swiftバージョン(ObjCから変換)

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    // Centering if there are fever pages
    let itemSize: CGSize? = (collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize
    let spacing: CGFloat? = (collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing

    let count: Int = self.collectionView(self, numberOfItemsInSection: section)
    let totalCellWidth = (itemSize?.width ?? 0.0) * CGFloat(count)
    let totalSpacingWidth = (spacing ?? 0.0) * CGFloat(((count - 1) < 0 ? 0 : count - 1))
    let leftInset: CGFloat = (bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2
    if leftInset < 0 {
        let inset: UIEdgeInsets? = (collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset
        return inset!
    }
    let rightInset: CGFloat = leftInset
    let sectionInset = UIEdgeInsets(top: 0, left: Float(leftInset), bottom: 0, right: Float(rightInset))
    return sectionInset
}

Untitled-3.png


Swiftコードの境界とは何ですか?未解決の識別子「境界」の使用エラーが発生します
Sachin Tanpure

こんにちは、私の例では、境界を持つUIView内にメソッドを実装しました。他の場所に実装している場合は、適切な境界を使用してください
Peter Lapisu


0

最も簡単な方法は、ストーリーボードまたはコードでコレクションビューの推定サイズを[なし]に設定することです layout.estimatedItemSize = CGSize.zero


0

グループごとに1つのセルのスペースしかない場合、a leading:およびtrailing:of .flexible(0)はセルを水平方向に中央揃えにします。

item.edgeSpacing = NSCollectionLayoutEdgeSpacing(
    leading: .flexible(0), top: nil,                                                     
    trailing: .flexible(0), bottom: nil
)

0

そのコードをプロジェクトで使用しました。これは両方向に水平および垂直collectionViewを中心.horizontal.vertical区間のインセットを使用します。設定されている場合、セクションの間隔と元のインセットを尊重します。デリゲートで使用するコード。これにより、再利用のUICollectionViewDelegateFlowLayoutためにから取得するUIcollectionViewか、ストーリーボードに設定する必要があるすべてのプロパティにアクセスできます。

// original function of the delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    // casting the layout as a UICollectionViewFlowLayout to have access to the properties of items for reusability - you could also link the real one from the storyboard with an outlet
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    // getting all the properties we need
    let itemWidth = flowLayout.itemSize.width
    let itemHeight = flowLayout.itemSize.height
    let interSpacing = flowLayout.minimumInteritemSpacing
    let lineSpacing = flowLayout.minimumLineSpacing
    // getting the size of the collectionView
    let collectionWidth = collectionView.bounds.width
    let collectionHeight = collectionView.bounds.height
    // getting the direction to choose how to align the collection
    let direction = flowLayout.scrollDirection
    // you don't want to have an item greater than the collection
    guard (itemWidth < collectionWidth && direction == .vertical) || (itemHeight < collectionHeight && direction == .horizontal) else {
        print("Really?")
        return UIEdgeInsets(top: flowLayout.sectionInset.top, left: flowLayout.sectionInset.left, bottom: flowLayout.sectionInset.bottom, right: flowLayout.sectionInset.right)
    }
    // getting the number of item in the current section
    let totalItemCount = CGFloat(collectionView.numberOfItems(inSection: section))
    // setting number of item in a row to the max number of items that can fit in a row without spacing or to the number of items in the section if less than the max
    var itemCountInRow = totalItemCount < (collectionWidth / itemWidth).rounded(.towardZero) ? totalItemCount : (collectionWidth / itemWidth).rounded(.towardZero)
    // how many max row can we have
    var countOfRow = totalItemCount < (collectionHeight / itemHeight).rounded(.towardZero) ? totalItemCount : (collectionHeight / itemHeight).rounded(.towardZero)
    // calculating the total width of row by multiplying the number of items in the row by the width of item and adding the spacing multiplied by the number of item minus one
    var totalWidthOfRow:CGFloat {
        get{
            return (itemWidth * itemCountInRow) + (interSpacing * (itemCountInRow - 1))
        }
    }
    // calculating the total height of row by multiplying the number of row by the height of item and adding the spacing multiplied by the number of row minus one
    var totalHeightOfRow:CGFloat {
        get{
            return (itemHeight * countOfRow) + (lineSpacing * (countOfRow - 1))
        }
    }
    // first we set the inset to the default
    var edgeInsetLeft = flowLayout.sectionInset.left
    var edgeInsetTop = flowLayout.sectionInset.top

    if direction == .vertical {
        // while the width of row with original margin is greater than the width of the collection we drop one item until it fits
        while totalWidthOfRow > collectionWidth || ((collectionWidth - totalWidthOfRow) / 2) < flowLayout.sectionInset.left {
            // droping an item to fit in the row
            itemCountInRow -= 1
        }
        // calculating the number of rows in collectionView by dividing the number of items by the number of items in a row
        countOfRow = (totalItemCount / (itemCountInRow)).rounded(.up)
    } else {
        itemCountInRow = (totalItemCount / countOfRow).rounded(.up)
        // while the height of row with original marginis greater than the height of the collection we drop one row until it fits
        while totalHeightOfRow >= collectionHeight  || ((collectionHeight - totalHeightOfRow) / 2) < flowLayout.sectionInset.top  {
            // droping an item to fit in the row
            countOfRow -= 1
        }
    }
    edgeInsetLeft = max(flowLayout.sectionInset.left, (collectionWidth - totalWidthOfRow) / 2)
    edgeInsetTop = max(flowLayout.sectionInset.top, (collectionHeight - totalHeightOfRow) / 2)
    // we don't specially need insets where the items are overflowing
    let edgeInsetRight = direction == .vertical ? edgeInsetLeft : flowLayout.sectionInset.right
    let edgeInsetBottom = direction == .horizontal ? edgeInsetTop : flowLayout.sectionInset.bottom
    // returning the UIEdgeInsets
    return UIEdgeInsets(top: edgeInsetTop, left: edgeInsetLeft, bottom: edgeInsetBottom, right: edgeInsetRight)
}

それが誰かを助けるホープ-それはない項目セクション内のセクションを中心に、より多くの我々はサブクラス化する必要があるためUICollectionViewFlowLayoutか、UICollectionViewLayoutアップルからモザイク例として。


-3

cellを中央に配置する必要があると思うので、collectionViewを使用する代わりに、UITableViewのように使用すると便利です。UIViewControllerを使用して、2つのUIViewを前後に配置しUITableView、中間に中間を配置するだけです。


写真を追加して、必要なものを正確に示します。ありがとうございます。
RaptoX
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.