Hücre aralığı ve UICollectionView - UICollectionViewFlowLayout boyut oranı nasıl ayarlanır?


137

Eklemeye çalışıyorum UICollectionView için ViewControllerve ben (bir ızgara gibi görünmelidir) hücreler arasındaki boş boşluk bırakmadan 'satır başına' 3 hücrelerini olması gerekir. Hücre genişliği ekran boyutunun üçte biri olmalıdır, bu yüzden layout.itemgenişliğin aynı olması gerektiğini düşündüm . Ama sonra anladım:

layout.itemSize width = screenSize.width / 3

Bu boyutu küçültürsem ( örneğin 7 veya 8 piksel ), daha iyidir, ancak satırdaki üçüncü hücre tamamen görünmez ve hala bu boş alana (üst ve alt ve sol ve sağ) sahipim.

resim açıklamasını buraya girin

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    var collectionView: UICollectionView?
    var screenSize: CGRect!
    var screenWidth: CGFloat!
    var screenHeight: CGFloat!

    override func viewDidLoad() {
        super.viewDidLoad()

        screenSize = UIScreen.mainScreen().bounds
        screenWidth = screenSize.width
        screenHeight = screenSize.height

        // Do any additional setup after loading the view, typically from a nib
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: screenWidth / 3, height: screenWidth / 3)
        collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        collectionView!.dataSource = self
        collectionView!.delegate = self
        collectionView!.registerClass(CollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
        collectionView!.backgroundColor = UIColor.greenColor()
        self.view.addSubview(collectionView!)
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as CollectionViewCell
        cell.backgroundColor = UIColor.whiteColor()
        cell.layer.borderColor = UIColor.blackColor().CGColor
        cell.layer.borderWidth = 0.5
        cell.frame.size.width = screenWidth / 3
        cell.frame.size.height = screenWidth / 3

        cell.textLabel?.text = "\(indexPath.section):\(indexPath.row)"
        return cell
    }
}

İşte çözümünüz. Teşekkürler.
janu kansagra

İşte Swift 4 için Çalışma Kodu stackoverflow.com/a/54703798/10150796
Nikunj Kumbhani

Yanıtlar:


299

Bu 2 satırı ekle

layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

Yani:

   // Do any additional setup after loading the view, typically from a nib.
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: screenWidth/3, height: screenWidth/3)
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        collectionView!.collectionViewLayout = layout

Bu, tüm boşlukları kaldıracak ve size bir ızgara düzeni sağlayacaktır:

resim açıklamasını buraya girin

İlk sütunun ekran genişliğine eşit bir genişliğe sahip olmasını istiyorsanız, aşağıdaki işlevi ekleyin:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    if indexPath.row == 0
    {
        return CGSize(width: screenWidth, height: screenWidth/3)
    }
    return CGSize(width: screenWidth/3, height: screenWidth/3);

}

Izgara düzeni şimdi görünecek (ayrıca ilk hücreye mavi bir arka plan ekledim): resim açıklamasını buraya girin


Çok teşekkür ederim, çok daha karmaşık bir şey bekliyordum ve bunun için çok zaman harcadım. Bir kez daha teşekkürler.
Marko

Ve sadece bir şey daha, sadece ilk hücre için layout.itemSize'i değiştirmek için herhangi bir olasılık var mı? (Ben ne zaman ı değişim cell.frame.size gerektiğini biliyoruz indexPath.row 0'dır ancak yalnızca bir öğe için düzen boyutunu değiştirmek için nasıl bilmiyorum) İlk eleman genişliği eşit olmalıdır screenWidth .
Marko

1
Merhaba, ben aynı sorun var ama ben Amaç C benzer işlev başlığı bilmek istiyorum.
Nada Gamal

1
Tamam, şimdi iyi çalışıyor, çok teşekkürler :) Amaç C işlevi: - (CGSize) collectionView: (UICollectionView ) collectionView düzen: (UICollectionViewLayout ) collectionViewLayout sizeForItemAtIndexPath: (NSIndexPath *) indexPath {return CGSizeMake (screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth / 3, screenWidth 3) ); }
Nada Gamal

4
büyük cevap için teşekkürler @greentor. bir ödül gönderdi. Unutmayın ! CollectionView'ın .collectionViewLayout = düzeni , okuyucuların
fattie

47

Swift 3 ve XCode 8 için bu işe yaradı. Bunu başarmak için aşağıdaki adımları izleyin: -

{
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    let width = UIScreen.main.bounds.width
    layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    layout.itemSize = CGSize(width: width / 2, height: width / 2)
    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 0
    collectionView!.collectionViewLayout = layout
}

Bu kodu viewDidLoad () işlevine yerleştirin.


32

Bazı durumlarda, ayarlama UICollectionViewFlowLayoutiçinde viewDidLoadveya ViewWillAppearCollectionView'ın üzerinde etkisi olmayabilir.

Ayar UICollectionViewFlowLayoutin viewDidAppearzamanında hücreler boyutlarda değişiklikleri görmek neden olabilir.

Swift 3'te Başka Bir Çözüm:

extension YourViewController : UICollectionViewDelegateFlowLayout{

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let collectionViewWidth = collectionView.bounds.width
        return CGSize(width: collectionViewWidth/3, height: collectionViewWidth/3)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 20
    }
}

Mükemmel cevap! Bu kesinlikle Apple'ın bunu yapmanın yolu. Şimdi, cihaz yönünü değiştirdiğinde nasıl yenileneceğini bilmiyorsunuz, değil mi?
jlstr

17

Swift 3 arıyorsanız, bunu başarmak için adımları izleyin:

func viewDidLoad() {

    //Define Layout here
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()

    //Get device width
    let width = UIScreen.main.bounds.width

    //set section inset as per your requirement.
    layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)

    //set cell item size here 
    layout.itemSize = CGSize(width: width / 2, height: width / 2)

    //set Minimum spacing between 2 items
    layout.minimumInteritemSpacing = 0

    //set minimum vertical line spacing here between two lines in collectionview
    layout.minimumLineSpacing = 0

    //apply defined layout to collectionview
    collectionView!.collectionViewLayout = layout

}

Bu, Swift 3 ile Xcode 8.0'da doğrulandı.


8
let layout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout
layout?.minimumLineSpacing = 8

4

Hızlı 4

let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
collectionViewLayout?.sectionInset = UIEdgeInsetsMake(0, 20, 0, 40) 
collectionViewLayout?.invalidateLayout()

1

Swift 3 ve XCode 8 için bu işe yaradı. Bunu başarmak için aşağıdaki adımları izleyin: -

viewDidLoad()
    {
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        var width = UIScreen.main.bounds.width
        layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    width = width - 10
    layout.itemSize = CGSize(width: width / 2, height: width / 2)
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        collectionView!.collectionViewLayout = layout
    }

3
Birden fazla bölümünüz varsa gerçeği nasıl dikkate alırsınız
Nikhil Pandey

sadece 1 sütun için (bölüm)
user924

0

Swift 3+ ve Xcode 9+ için Bunu kullanmayı deneyin

extension ViewController: UICollectionViewDelegateFlowLayout {

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

    let collectionWidth = collectionView.bounds.width
    return CGSize(width: collectionWidth/3, height: collectionWidth/3)

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0

}

0

Swift 5: Kapsayıcı alanından en iyi şekilde yararlanmak için dinamik hücre genişliğine sahip hücreler arasında eşit olarak dağıtılmış alanlar için, bir minimumCellWidth değeri sağlayarak aşağıdaki kod snippet'ini kullanabilirsiniz .

private func collectionViewLayout() -> UICollectionViewLayout {
    
    let layout = UICollectionViewFlowLayout()
    layout.sectionHeadersPinToVisibleBounds = true
    // Important: if direction is horizontal use minimumItemSpacing instead. 
    layout.scrollDirection = .vertical
    
    let itemHeight: CGFloat = 240
    let minCellWidth :CGFloat = 130.0
    let minItemSpacing: CGFloat = 10
    let containerWidth: CGFloat = self.view.bounds.width
    let maxCellCountPerRow: CGFloat =  floor((containerWidth - minItemSpacing) / (minCellWidth+minItemSpacing ))
    
    let itemWidth: CGFloat = floor( ((containerWidth - (2 * minItemSpacing) - (maxCellCountPerRow-1) * minItemSpacing) / maxCellCountPerRow  ) )
    // Calculate the remaining space after substracting calculating cellWidth (Divide by 2 because of left and right insets)
    let inset = max(minItemSpacing, floor( (containerWidth - (maxCellCountPerRow*itemWidth) - (maxCellCountPerRow-1)*minItemSpacing) / 2 ) )

    
    layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
    layout.minimumInteritemSpacing = min(minItemSpacing,inset)
    layout.minimumLineSpacing = minItemSpacing
    layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)

    
    return layout
}
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.