Bagaimana cara memusatkan Sel UICollectionView secara horizontal?


124

Saya telah melakukan beberapa penelitian, tetapi saya tidak dapat menemukan contoh kode apa pun tentang cara memusatkan sel di UICollectionView secara horizontal.

alih-alih sel pertama seperti X00 ini , saya ingin menjadi seperti ini 0X0 . apakah ada cara untuk mencapai ini?

EDIT:

untuk memvisualisasikan apa yang saya inginkan:

masukkan deskripsi gambar di sini

Saya membutuhkannya agar terlihat seperti versi B ketika hanya ada satu elemen di CollectionView. Ketika saya mendapatkan lebih dari satu elemen, maka itu harus seperti versi A tetapi dengan lebih banyak elemen.

Saat ini sepertinya Versi A ketika saya hanya memiliki 1 elemen, dan saya bertanya-tanya bagaimana saya bisa membuatnya terlihat seperti B.

Terima kasih untuk bantuannya!


Bukankah lebih mudah membiarkan sel menyesuaikan dengan lebar tampilan koleksi lalu memusatkan tampilan koleksi itu sendiri di dalam induknya?
Arthur Gevorkyan

ya, setidaknya ada dua cara untuk melakukan ini, pertama (cepat) adalah membuat lebar sel dari seluruh layar dan memusatkan tampilan anaknya. kedua (kanan) menerapkan tata letak tampilan koleksi khusus
sage444

Pada akhirnya akan ada lebih banyak sel yang datang dari backend, mengisi seluruh lebar bukanlah ide yang baik
RaptoX

meningkatkan lebar cukup untuk ditetapkan di pusat
Kishore Kumar

Jawaban:


228

Ini bukan ide yang baik untuk menggunakan perpustakaan, jika tujuan Anda hanya ini yaitu untuk meratakan tengah.

Lebih baik Anda bisa melakukan penghitungan sederhana ini dalam fungsi collectionViewLayout Anda.

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. Terima kasih banyak atas jawaban yang saya terapkan ini dan barisnya berada di tengah sebagaimana mestinya tetapi sekarang masalahnya adalah saya tidak dapat menggulir ke item pertama. Ketika saya mencoba untuk menggulir ke item pertama itu membawa saya kembali ke UIEdgeInsets yang dimodifikasi. Anda dapat melihat aplikasi demo saya github.com/anirudha-music/CollectionViewCenter
Anirudha Mahale

5
Di Swift 3, tanda tangan metode baru adalah collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int).
Kamchatka

1
bagaimana Anda bisa mengambil cellWidth, apakah mungkin melalui metode cellForItemAt? saya mencoba dan hasilnya nihil .. lebar sel untuk saya berubah berdasarkan ukuran layar .. @DarshanPatel.
Chris

10
@Distroartonline. Jawaban Anda terkadang dapat menghasilkan nilai negatif pada perangkat yang lebih kecil. Pertimbangkan untuk menggunakan pemeriksaan maksimal pada leftInsetnilai Anda seperti ini:let leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
Rhuari Glen

3
Jika Anda tidak membuat subclass UICollectionViewController, pastikan kelas Anda sesuai dengan UICollectionViewDelegateFlowLayout jika tidak maka tidak akan berfungsi
Saeed Ir

59

Swift 5.1.0

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.0

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)

}

Cepat 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)

    }

jangan lupa tambahkan protokolnya

UICollectionViewDelegateFlowLayout

kendala mungkin @ashForIos
Ahmed Safadi

Jawaban Anda berfungsi dengan baik jika ada sel yang sesuai dengan collectionView saat jumlah sel meningkat, sel berada di tengah dan Anda tidak dapat menggulir ke sel pertama atau terakhir.
NickCoder

2
@Vitalii 80 berarti Lebar sel, dan 10 spasi antar sel, jika Anda membaca nama variabel Anda akan mengerti apa artinya: P
Ahmed Safadi

Solusi Swift 4.2 lebih mudah, TERIMA KASIH! Pastikan untuk menyetel "80" ke berapa pun lebar objek sel Anda yang sebenarnya.
John Pitts

25

Coba ini untuk 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)
    }

Tambahkan cellWidth Anda sebagai gantinya 165.0


1
ini adalah jawaban terbaik. Dengan matematika paling sederhana di dalamnya. bekerja dengan sejumlah baris dan kolom
rickrvo

20

Saya menggunakan KTCenterFlowLayout untuk ini, dan ini berfungsi dengan baik. Ini adalah subkelas khusus dari UICollectionViewFlowLayoutsel pusat yang Anda inginkan. (Catatan: ini bukan hal yang sepele untuk diselesaikan dengan memposting beberapa kode, itulah sebabnya saya menautkan ke proyek GitHub!)


Tidak dapat membuatnya berhasil dari IB. Perpustakaan ini bekerja seperti pesona bagi saya. Baru saja menginstal pod dan mengubah kelas tata letak di IB!
tagirkaZ

15

Versi objektif-C dari jawaban Darshan Patel :

- (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;
}

Terima kasih. Ini bekerja dengan baik dengan satu baris. tetapi menimbulkan masalah di beberapa baris. Saya tidak dapat menambahkan url di sini untuk menunjukkan tangkapan layar. . tetapi Anda dapat menambahkan "yynoalzg" di url kecil. kamu akan mendapatkan ide. Bagian emas memiliki 4 rekor. 4 harus di baris baru. .tapi setelah metode ini akan ditampilkan seperti itu ... beri tahu saya jika ada ide.
Hitarth

6

Sedikit mengubah jawaban @Safad Funy, inilah yang berhasil bagi saya di versi terbaru Swift & iOS. Dalam hal ini saya ingin lebar sel menjadi sepertiga dari ukuran tampilan koleksi.

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
Ini bekerja untuk saya terutama, ketika hanya ada satu sel.
Dasoga

6

Anda dapat menggunakan ekstensi ini (Swift 4).

Itu dapat memusatkan sel dengan jika Anda collectionViewpunya layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize.

Ini bekerja dengan ukuran sel apa pun dan bekerja dengan sempurna saat 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)
    }
}

Semoga membantu Anda!


1
Mendapatkan kesalahan: Utas 1: EXC_BAD_ACCESS (kode = 2, alamat = 0x118ffde58)
atulkhatri

4

Swift 4.2 (Secara Horizontal dan Vertikal). Ini peningkatan kecil dari kode Pink Panther dan terima kasih banyak padanya!


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)

    }
}

Pastikan kelas Anda sesuai dengan protokol UICollectionViewDelegateFlowLayout


Sungguh kode Anda berfungsi dengan baik untuk saya, terima kasih Bung; )
steveSarsawa

4

Berikut adalah versi yang lebih baru untuk Swift 5 yang juga berfungsi dengan baik saat sel lebih dari satu baris:

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
    }
}

Harap pastikan kelas Anda sesuai dengan UICollectionViewDelegateFlowLayoutprotokol.


3

Cepat 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

Untuk orang yang hanya ingin menambahkan padding ( atas, kiri, bawah, kanan ):

Tambahkan protokol UICollectionViewDelegateFlowLayout

Contoh ini menunjukkan padding kiri dan kanan dengan 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

Anda dapat mencoba solusi saya, ini berfungsi dengan baik,

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

Jawaban yang diterima adalah jawaban yang benar tetapi jika Anda totalCellWidthkurang dari CollectionViewitu width, tetapi hanya untuk menjaganya, Anda dapat melakukan seperti di bawah ini.

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

1

Kode ini harus memusatkan tampilan koleksi secara horizontal bahkan di Swift 4.0 tanpa modifikasi apa pun:

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
    }
}

Pastikan kelas Anda sesuai dengan UICollectionViewDelegateFlowLayoutprotokol


0

Saya akhirnya mengambil pendekatan yang sama sekali berbeda di sini, yang menurut saya layak untuk disebutkan.

Saya menetapkan batasan pada tampilan koleksi saya agar sejajar secara horizontal di tengah. Kemudian saya menetapkan batasan lain yang menentukan lebarnya. Saya membuat outlet untuk batasan lebar di dalam viewController saya yang menyimpan tampilan koleksi. Kemudian, ketika sumber data saya diubah dan saya memperbarui tampilan koleksi, saya menghitung jumlah sel dan melakukan kalkulasi (sangat mirip) untuk menyetel ulang lebarnya.

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

Kemudian saya menetapkan nilai outlet kendala .constantke hasil kalkulasi dan autolayout melakukan sisanya.

Ini mungkin bertentangan dengan `UICollectionViewDelegateFlowLayout, tetapi ini bekerja dengan sempurna bagi saya untuk membuat tampilan koleksi rata kiri. Tanpa delegasi, tampaknya hanya berfungsi jika sel memenuhi sebagian besar tampilan.


0

Solusi umum untuk tata letak alur yang memusatkan halaman jika kurang dari lebarnya dan sejajar ke kiri jika ada lebih banyak

- (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;
}

Versi Swift (dikonversi dari 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


Apa batas dalam kode swift? Saya mendapatkan kesalahan penggunaan 'batas' pengenal yang tidak terselesaikan
Sachin Tanpure

Hai, dalam contoh saya, saya menerapkan metode di dalam UIView, yang memiliki batas, jika Anda menerapkannya di tempat lain, gunakan batas yang sesuai
Peter Lapisu


0

cara termudah adalah menyetel ukuran perkiraan tampilan koleksi ke Tidak Ada di storyboard atau dengan kode layout.estimatedItemSize = CGSize.zero


0

Jika hanya ada ruang untuk satu sel per grup, a leading:dan trailing:dari .flexible(0)akan memusatkan sel secara horizontal:

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

0

Saya menggunakan kode itu dalam sebuah proyek. Ini memusatkan collectionView secara horizontal dan vertikal di kedua arah .horizontaldan .verticalmenggunakan sisipan bagian. Menghormati jarak dan inset asli bagian tersebut jika disetel. Kode untuk digunakan dalam delegasi UICollectionViewDelegateFlowLayoutsehingga kita memiliki akses ke semua properti yang perlu kita ambil dari UIcollectionViewatau set di storyboard untuk digunakan kembali.

// 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)
}

Semoga ini dapat membantu seseorang - ini memusatkan bagian bukan item di dalam bagian, untuk lebih lanjut kita harus subkelas UICollectionViewFlowLayoutatau UICollectionViewLayoutsebagai contoh mosaik dari Apple.


-4

Saya pikir Anda perlu ke tengah sel, jadi daripada menggunakan collectionView, saya ingin UITableView akan sangat berguna. Cukup gunakan UIViewController dan letakkan dua UIViews di depan dan belakang dan letakkan UITableViewdi tengah Semoga ini bisa membantu


Saya menambahkan gambar, untuk menunjukkan kepada Anda apa yang sebenarnya saya butuhkan, terima kasih!
RaptoX
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.