UICollectionView Hücreleri yatay olarak nasıl ortalanır?


124

Biraz araştırma yaptım, ancak UICollectionView'da hücrelerin yatay olarak nasıl ortalanacağına dair herhangi bir kod örneği bulamadım.

yerine ilk hücre böyle olma X00 , ben böyle olmasını istiyorum 0x0 . bunu başarmanın bir yolu var mı?

DÜZENLE:

istediğimi görselleştirmek için:

görüntü açıklamasını buraya girin

CollectionView'da yalnızca bir öğe olduğunda sürüm B'ye benzemesine ihtiyacım var. Birden fazla elemana sahip olduğumda, o zaman A sürümüne benzemeli ama daha çok elemanlı olmalı.

Şu anda sadece 1 elementim varken Versiyon A gibi görünüyor ve nasıl B'ye benzeyebileceğimi merak ediyorum

Yardım için teşekkürler!


Hücrenin koleksiyon görünümünün genişliğine sığmasına izin vermek ve ardından koleksiyon görünümünün kendisini üst öğesi içinde ortalamak daha kolay değil mi?
Arthur Gevorkyan

evet, bunu yapmanın en az iki yolu vardır, birincisi (hızlı) tüm ekranın hücre genişliğini yapmak ve alt görünümünü ortalamaktır. ikinci (sağda) özel koleksiyon görünümü düzenini uygula
uygula

Sonunda arka uçtan daha fazla hücre gelecektir, tüm genişliği doldurmak iyi bir fikir olmayacaktır.
uçtan

genişliği artırmak merkezde ayarlamak için yeterlidir
Kishore Kumar

Yanıtlar:


229

Amacınız sadece bu, yani ortaya hizalamaksa, bir kitaplık kullanmak iyi bir fikir değildir.

Daha iyisi, collectionViewLayout fonksiyonunuzda bu basit hesaplamayı yapabilirsiniz.

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. Bunu uyguladığım cevap için çok teşekkürler ve satırlar olması gerektiği gibi ortaya çıktı ama şimdi sorun ilk maddeye kaydıramıyorum. İlk öğeye kaydırmaya çalıştığımda, beni değiştirilmiş UIEdgeInsets'e geri getiriyor. Demo uygulamamı görebilirsiniz github.com/anirudha-music/CollectionViewCenter
Anirudha Mahale

5
Swift 3'te yeni yöntem imzası collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int).
Kamçatka

1
cellWidth'i nasıl yakalayabilirsiniz, bu cellForItemAt yöntemi ile mümkün mü? denedim ve sıfır döndü .. ekran boyutuna göre benim için hücre genişliği değişiklikleri .. @DarshanPatel.
Chris

10
@DarshanPatel. Cevabınız bazen daha küçük cihazlarda negatif bir değer üretebilir. leftInsetDeğeriniz için şu şekilde bir maksimum kontrol kullanmayı düşünün :let leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
Rhuari Glen

3
UICollectionViewController'ı alt sınıflara ayırmıyorsanız, sınıfınızın UICollectionViewDelegateFlowLayout'a uygun olduğundan emin olun, aksi takdirde çalışmaz
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)

}

Hızlı 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)

    }

protokolü eklemeyi unutma

UICollectionViewDelegateFlowLayout

kısıtlama belki @ashForIos
Ahmed

Cevabınız, collectionView'a uyan hücreler olduğunda iyi çalışıyor Hücre sayısı arttığında hücreler merkezdedir ve ilk veya son hücrelere kaydıramazsınız.
NickCoder

2
@Vitalii 80, hücre genişliği ve 10 hücreler arasındaki boşluk anlamına gelir, değişken adını okursanız bunun ne anlama geldiğini anlarsınız: P
Ahmed Safadi

Swift 4.2 çözümü daha kolay, TEŞEKKÜRLER! Sadece "80" değerini gerçek hücre nesnesi genişliğinize göre ayarladığınızdan emin olun.
John Pitts

25

Bunu Swift 4 için deneyin

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

165.0 yerine hücre genişliğinizi ekleyin


1
bu en iyi cevap. En basit matematik ile. herhangi bir sayıda satır ve sütunla çalışır
rickrvo

20

Bunun için KTCenterFlowLayout kullanıyorum ve harika çalışıyor. Bu, UICollectionViewFlowLayouthücreleri istediğiniz gibi merkezleyen özel bir alt sınıftır . (Not: Bu, bazı kodlar göndererek çözülmesi gereken önemsiz bir şey değil, bu yüzden bir GitHub projesine bağlanıyorum!)


IB'den çalışmasını sağlayamadı. Bu kütüphane benim için bir cazibe merkezi oldu. Sadece bölmeyi kurdu ve IB'deki düzen sınıfını değiştirdi!
tagirkaZ

15

Darshan Patel'in cevabının nesnel-C versiyonu :

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

Teşekkürler. Tek sıra ile sorunsuz çalışıyor. ancak birden çok satırda sorun yaratıyor. u ekran görüntüsünü göstermek için buraya url ekleyemiyorum. . ancak küçük url'ye "yynoalzg" ekleyebilirsiniz. fikir alacaksın. Altın bölümünde 4 rekor var. 4. yeni satırda olmalıdır. .ama bu yöntemden sonra böyle görünür ... herhangi bir fikir varsa bana bildirin.
Hitarth

6

@Safad Funy'nin cevabını biraz değiştirerek, Swift ve iOS'un en son sürümünde benim için işe yarayan şey buydu. Bu durumda, hücre genişliğinin koleksiyon görünümünün üçte biri kadar olmasını istedim.

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
Bu benim için özellikle tek bir hücre olduğunda işe yaradı.
Dasoga

6

Bu eklentiyi (Swift 4) kullanabilirsiniz.

Bu eğer hücreleri ortalayabilmek collectionViewvarlayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize .

Herhangi bir hücre boyutuyla çalışır ve ne zaman mükemmel çalışır? 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)
    }
}

Umarım size yardımcı olur!


1
Hata alma: Konu 1: EXC_BAD_ACCESS (kod = 2, adres = 0x118ffde58)
atulkhatri

4

Swift 4.2 (Yatay ve Dikey). Pembe Panter kodunun küçük bir yükseltmesi ve ona çok teşekkürler!


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)

    }
}

Sınıfınızın UICollectionViewDelegateFlowLayout protokolüne uygun olduğundan emin olun


Gerçekten kodun benim için harika çalışıyor, teşekkürler Dostum; )
steveSarsawa

4

Hücreler birden fazla satır olduğunda da iyi çalışan Swift 5'in yeni sürümü :

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

Emin sınıf olun uyan, hiç UICollectionViewDelegateFlowLayoutprotokolü.


3

Swift 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

Yalnızca dolgu eklemek isteyenler için ( üst, sol, alt, sağ ):

Protokolü ekleyin UICollectionViewDelegateFlowLayout

Bu örnek, 40 ile sol ve sağ dolguyu göstermektedir.

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

Çözümümü deneyebilirsiniz, iyi çalışıyor,

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

Kabul cevap doğru cevap ama senin eğer totalCellWidthdaha azdır CollectionView's widthbuna karşı, ama sadece görevlisine aşağıda olarak yapabilirsiniz.

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

1

Bu kod, herhangi bir değişiklik yapılmadan Swift 4.0'da bile koleksiyon görünümünü yatay olarak ortalamalıdır :

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

Sınıfınızın UICollectionViewDelegateFlowLayoutprotokole uygun olduğundan emin olun


0

Burada tamamen farklı bir yaklaşım benimsemeye başladım ve bundan bahsetmeye değer olduğuna inanıyorum.

Koleksiyon görünümümün merkezde yatay olarak hizalanması için bir sınırlama belirledim. Sonra genişliği belirleyen başka bir kısıtlama ayarladım. Koleksiyon görünümünü tutan viewController'ımın içinde genişlik kısıtlaması için bir çıkış oluşturdum . Daha sonra, veri kaynağım değiştiğinde ve koleksiyon görünümünü güncellediğimde, hücre sayısını alıyorum ve genişliği sıfırlamak için (çok benzer) bir hesaplama yapıyorum.

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

Daha sonra kısıtlama çıkışının .constantdeğerini hesaplama sonucuna ayarlıyorum ve gerisini otomatik düzen hallediyor.

Bu, UICollectionViewDelegateFlowLayout ile çelişebilir, ancak bu, sola dayalı bir koleksiyon görünümü oluşturmam için mükemmel bir şekilde çalıştı. Temsilci olmadan, sadece hücreler görüşün çoğunu doldurduğunda işe yarıyor gibi görünüyor.


0

Sayfaları genişlikten azsa ortalayan ve daha fazla varsa sola hizalayan akış düzeni için genel çözüm

- (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 sürümü (ObjC'den dönüştürülmüş)

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
}

Başlıksız-3.png


Swift kodunun sınırları nedir? Çözülmemiş tanımlayıcı 'sınırlar' hatası alıyorum
Sachin Tanpure

Merhaba,
örneğimde


0

en basit yol, koleksiyon görünümü tahmin boyutunu film şeridinde veya kodla Yok olarak ayarlamaktır layout.estimatedItemSize = CGSize.zero


0

Grup başına yalnızca bir hücre için yer varsa, a leading:ve trailing:of .flexible(0)hücreyi yatay olarak ortalayacaktır:

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

0

Bu kodu bir projede kullandım. CollectionView öğesini yatay ve dikey olarak her iki yönde .horizontalve .verticalbölüm eklerini kullanarak ortalar . Ayarlanmışsa bölümün boşluğuna ve orijinal ekine saygı duyar. Temsilcide kullanılacak kod, UICollectionViewDelegateFlowLayoutböylece UIcollectionViewyeniden kullanılabilirlik için film şeridinden almamız veya film şeridinde ayarlamamız gereken tüm özelliklere erişebiliriz .

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

Umarım birine yardımcı olur - bölümün içindeki öğeleri değil bölümü merkezler, daha çok Apple'ın mozaik örneği olarak UICollectionViewFlowLayoutveya alt sınıfına almamız gerekir UICollectionViewLayout.


-4

Sanırım hücreyi ortalamanız gerekiyor, bu yüzden collectionView yerine UITableView çok kullanışlı olacak. Sadece önünde bir UIViewController ve yer iki UIViews kullanmak ve geri bir koyun UITableVieworta Hope bu yardımcı olur


Tam olarak neye ihtiyacım olduğunu göstermek için bir resim ekledim, teşekkürler!
RaptoX
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.