วิธีการตั้งค่าระยะห่างระหว่างเซลล์และ UICollectionView - อัตราส่วนขนาด UICollectionViewFlowLayout


137

ฉันพยายามที่จะเพิ่มUICollectionViewการViewControllerและฉันจะต้องมี 3 เซลล์ต่อแถว 'โดยไม่ต้องช่องว่างระหว่างเซลล์ (มันควรมีลักษณะเช่นตาราง) ความกว้างของเซลล์ควรเป็นหนึ่งในสามของขนาดหน้าจอดังนั้นฉันคิดว่าความlayout.itemกว้างควรเท่ากัน แต่ฉันได้รับสิ่งนี้:

layout.itemSize width = screenSize.width / 3

ถ้าฉันลดขนาดนั้น (โดย7หรือ8 พิกเซลเช่น) มันจะดีกว่า แต่เซลล์ที่สามในแถวไม่สามารถมองเห็นได้อย่างสมบูรณ์และฉันยังมีพื้นที่ว่างนั้น (บน & ล่างและซ้ายและขวา)

ป้อนคำอธิบายรูปภาพที่นี่

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

นี่คือทางออกของคุณ ขอบคุณ
janu kansagra

นี่คือรหัสการทำงานสำหรับ Swift 4 stackoverflow.com/a/54703798/10150796
Nikunj Kumbhani

คำตอบ:


299

เพิ่ม 2 บรรทัดเหล่านี้

layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

ดังนั้นคุณมี:

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

ที่จะลบช่องว่างทั้งหมดและให้เค้าโครงตาราง:

ป้อนคำอธิบายรูปภาพที่นี่

หากคุณต้องการให้คอลัมน์แรกมีความกว้างเท่ากับความกว้างของหน้าจอให้เพิ่มฟังก์ชั่นต่อไปนี้:

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

}

เค้าโครงกริดจะมีลักษณะเป็นเช่นนี้ (ฉันได้เพิ่มพื้นหลังสีน้ำเงินไปยังเซลล์แรก): ป้อนคำอธิบายรูปภาพที่นี่


ขอบคุณมากฉันคาดหวังว่าจะมีสิ่งที่ซับซ้อนกว่านี้มากและฉันใช้เวลาไปกับมันมาก ขอบคุณอีกครั้ง
Marko

และมีอีกอย่างหนึ่งที่มีความเป็นไปได้ที่จะเปลี่ยนlayout.itemSizeสำหรับเซลล์แรกเท่านั้นหรือไม่ (ฉันรู้ว่าฉันต้องเปลี่ยนแปลง cell.frame.size เมื่อindexPath.rowเป็น 0 แต่ไม่ทราบวิธีการเปลี่ยนรูปแบบขนาดเพียงหนึ่งรายการ) ความกว้างองค์ประกอบแรกควรจะเท่ากับscreenWidth
Marko

1
สวัสดีฉันมีปัญหาเดียวกัน แต่ฉันต้องการทราบชื่อฟังก์ชันที่คล้ายกันใน Objective C
Nada Gamal

1
ตกลงมันทำงานได้ดีในตอนนี้ขอบคุณมาก :) ฟังก์ชั่น C Objective: - (CGSize) collectionView: (UICollectionView ) collectionView เลย์เอาต์: (UICollectionViewLayout ) collectionViewLayout sizeForItemAtIndexPath: (NSIndexPath *) ); }
Nada Gamal

4
ขอบคุณสำหรับคำตอบที่ดี @greentor ส่งเงินรางวัล อย่าลืมคอลเล็กชัน
View! .collectionViewLayout

47

สำหรับ Swift 3 และ XCode 8สิ่งนี้ใช้ได้ ทำตามขั้นตอนด้านล่างเพื่อบรรลุสิ่งนี้: -

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

วางรหัสนี้ในฟังก์ชั่น viewDidLoad ()


32

ในบางสถานการณ์การตั้งค่าUICollectionViewFlowLayoutในviewDidLoadหรือViewWillAppearอาจไม่ส่งผลกระทบต่อ collectionView

การตั้งค่าUICollectionViewFlowLayoutในviewDidAppearอาจทำให้เห็นการเปลี่ยนแปลงของขนาดเซลล์ในรันไทม์

โซลูชันอื่นใน Swift 3:

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

คำตอบที่ดี! นี่เป็นวิธีที่ Apple ทำ ทีนี้คุณไม่รู้วิธีการรีเฟรชเมื่ออุปกรณ์เปลี่ยนทิศทาง
jlstr

17

หากคุณกำลังมองหา Swift 3 ทำตามขั้นตอนต่อไปนี้:

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

}

สิ่งนี้ได้รับการยืนยันใน Xcode 8.0 ด้วย Swift 3



4

สวิฟต์ 4

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

1

สำหรับ Swift 3 และ XCode 8สิ่งนี้ใช้ได้ ทำตามขั้นตอนด้านล่างเพื่อบรรลุสิ่งนี้: -

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
วิธีคำนึงถึงข้อเท็จจริงถ้าคุณมีหลายส่วน
Nikhil Pandey

เป็นเพียง 1 คอลัมน์ (ส่วน)
user924

0

สำหรับ Swift 3+ และ Xcode 9+ ลองใช้สิ่งนี้

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:สำหรับช่องว่างที่กระจายอย่างสม่ำเสมอระหว่างเซลล์ที่มีความกว้างของเซลล์แบบไดนามิกเพื่อใช้ประโยชน์สูงสุดจากพื้นที่คอนเทนเนอร์คุณสามารถใช้ข้อมูลโค้ดด้านล่างได้โดยระบุค่า

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
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.