CollectionView sizeForItemAtIndexPath ไม่เคยเรียก


96

นี่มันทำให้ฉันแทบคลั่ง! ฉันมี UICollectionViewController ดังที่แสดงด้านล่าง:

class PhrasesCompactCollectionViewController: UICollectionViewController

numberOfSections และ cellForItemAt ถูกเรียก แต่ sizeForItemAtIndexPath จะไม่ถูกเรียก ฉันใช้รหัสเดียวกันกับที่อื่นและทำงานอย่างถูกต้อง ฉันใช้ Xcode 8 Beta 6

func collectionView(collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath:  NSIndexPath) -> CGSize {

        return CGSize(width: 120, height:120) 
    }

คำตอบ:


255

คุณต้องระบุว่าคุณใช้โปรโตคอลUICollectionViewDelegateFlowLayoutในการประกาศคลาสของคุณ

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout


11
ฉันทำสิ่งนี้แล้วแต่ยังไม่เรียก :(
Van Du Tran

58

ในSwift 3+ใช้วิธีนี้:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width:(collectionView.frame.height-90)/2, height: 100)
}

ตรวจสอบให้แน่ใจว่าชั้นเรียนของคุณสอดคล้องกับทั้ง Delegate

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout


4
เป็นเรื่องซ้ำซ้อนที่ต้องปฏิบัติตามUICollectionViewDelegateที่ UICollectionViewController ทำอยู่แล้ว
Van Du Tran

3
@VanDuTran ไม่ซ้ำซ้อนที่จะระบุว่าจำเป็นเพราะไม่จำเป็นต้องเป็น UICollectionViewController ...
Michael Hudson

ฉันคิดว่าคุณหมายถึงมุมมองที่ไม่ใช่คอลเลกชัน Viewcontroller สามารถเป็น UICollectionViewDelegate
ScottyBlades

1
UICollectionViewDelegateFlowLayout สืบทอดมาจาก UICollectionViewDelegate ดังนั้นเพียงใช้ UICollectionViewDelegateFlowLayout
evya

49

ผมมีปัญหาเหมือนกัน. สิ่งหนึ่งที่ช่วยฉันคือการสร้าง 'ขนาดโดยประมาณ' สำหรับขนาดเซลล์ภายใต้ตัวตรวจสอบขนาด collectionView 'ไม่มี'

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


9
คุณช่วยเพื่อนในวันของฉันคุณเป็นฮีโร่
Asif Ali

1
คำตอบอื่น ๆ ทั้งหมดในโพสต์อื่น ๆ ทั้งหมดเกี่ยวกับการใช้sizeForItemAtไม่ได้กล่าวถึงสิ่งนี้ มีประโยชน์มาก.
JCutting8

มันบ้าไปแล้ว!!!! ฉันทดสอบบนเครื่องจำลอง iPhone 5 ด้วย iOS เวอร์ชัน 10.3.1 และวิธีการเรียก บนเครื่องจำลอง iPhone 5s ด้วยวิธีเวอร์ชัน 10.3.1 ไม่ได้รับการเรียก !!! ฉันเปลี่ยนขนาดโดยประมาณเป็นไม่มี มันเริ่มถูกเรียกใช้บน iPhone 5s WT WT WT
hasan

ขอบคุณมาก! มุมมองคอลเลกชันของฉันกับแบบกำหนดเองsizeForItemAtทำงานได้ดีจนถึง Xcode 11.4 เมื่อเซลล์มีความกว้างไม่ถูกต้อง พยายามหลายอย่างและในที่สุดก็ได้ผล
Filip

คุณประหยัดเวลาของฉัน ขอบคุณมาก.
Shahbaz Akram

17

สวิฟต์ 5

ต้องทำตามขั้นตอนเหล่านี้ทั้งหมด:

  1. สอดคล้องกับUICollectionViewDelegateFlowLayout <== จำเป็นอย่างยิ่ง !!
  2. และ UICollectionViewDelegate, UICollectionViewDataSource
  3. ตั้งค่าสิ่งเหล่านี้ใน viewDidLoad: collectionView.delegate = selfและcollectionView.dataSource = self
  4. ตั้งค่าEstimate Size เป็น Noneใน Interface Builder
  5. ตรวจสอบว่าเมธอดต่อไปนี้มีsizeForItemAtและไม่ใช่sizeForItemAtIndexPath

เช่น :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 100, height:100)
} 

3
ประมาณขนาดเป็นไม่มี - บันทึกวันของฉัน!
Joe Hallenbeck

ยอมรับคำตอบนี้ถูกต้อง!
NickCoder

15

สวิฟต์ 3

ในการตั้งค่าขนาดเซลล์ของ UICollectionView คุณต้องสร้างและปรับแต่งวัตถุของUICollectionViewFlowLayout. ปรับแต่งคุณสมบัติและตั้งค่าวัตถุโครงร่างนั้นเป็นวัตถุ UICollectionView

เปลี่ยนความสูงและความกว้างของเซลล์วัตถุตามความต้องการของคุณ (ความสูงและความกว้างของเซลล์ที่คุณต้องการ)

override func viewDidLoad() {
    super.viewDidLoad()

    let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
    let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
    let cellSize = CGSize(width: cellWidth , height:cellheight)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

ตรวจสอบให้แน่ใจ: หากคุณเพิ่มเมธอด sizeForItemAt indexPath แล้วต้องลบเมธอด ...

วิธีลบด้านล่าง

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

}

12
สิ่งนี้มีประโยชน์อย่างไร
อัลมาส

1
Almas ซึ่งจะเป็นประโยชน์สำหรับการตั้งค่าขนาดเซลล์ที่กำหนดเองของ UICollectionViewCell ... มีตัวแปร cellWidth และ cellHeight ซึ่งคุณสามารถกำหนดค่าของคุณเองได้ ... เช่นเดียวกับ "layout.sectionInset", "layout.minimumLineSpacing" และ "layout .minimumInteritemSpacing "ตัวแปรเหล่านี้มีความสำคัญสำหรับขนาด UICollectionViewCell ด้วย ..
Gaurav Rami

2
สิ่งนี้ใช้ได้เฉพาะเมื่อเซลล์ทั้งหมดมีขนาดเท่ากัน คำตอบด้านล่างคือคำตอบที่ถูกต้อง
JeffN

นี่คือการเปลี่ยนขนาดของ UICollectionView แต่ไม่ใช่เซลล์ในมุมมอง
Async-

นี่ไม่ใช่คำตอบว่าเหตุใดจึงไม่เรียกวิธีการมอบหมาย
Ziv Kesten

6

ชั้นหนึ่งต้องยืนยันกับ UICollectionViewDelegateFlowLayout จากนั้นคุณต้องเขียนโค้ดต่อไปนี้ใน viewDidLoad ():

// เพื่อบอกให้ UICollectionView ใช้เมธอด UICollectionViewDelegateFlowLayout ของ UIViewController

collectionView.delegate = self

// หากคุณต้องการตั้งค่าเค้าโครงโฟลว์มุมมองคอลเลคชันของคุณเอง

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view

self.collectionView?.setCollectionViewLayout(layout, animated: true)

โดยใช้รหัสนี้วิธี UICollectionViewDelegateFlowLayout

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

จะถูกเรียกคุณสามารถกำหนดขนาดด้วยวิธีนี้


4

สามสิ่งที่คุณต้องตรวจสอบว่าคำตอบไม่ได้ผล:

  1. ใช้ FlowLayout Delegate: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. ใช้วิธีการกำหนดขนาดของรายการสำหรับ swift 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width) }

  3. เลือกEstimate size = Noneในตรวจสอบองค์ประกอบของ UICollectionView


2

ฉันมีปัญหาเดียวกันและไม่มีอะไรจะแก้ไขได้ ฉันมีคำเตือนสีเหลืองแจ้งว่าให้ทำให้เป็นส่วนตัวเนื่องจากใกล้เคียงกับฟังก์ชันอื่นที่กำหนดโดย Layout Delegate สิ่งที่แก้ไขสำหรับฉันคือ:

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

สังเกตความแตกต่างจาก "sizeForItemAtIndexPath" เป็น "sizeForItemAt" ที่ถูกต้อง

ฉันฉีกผมออกเป็นเวลาหลายวันเพื่อพยายามคิดออกและในที่สุดมันก็ได้ผล ด้านล่างฉันจะรวมฟังก์ชันทั้งหมดของฉันเพื่อแสดงให้คุณเห็นว่าฉัน "ซ่อน" เซลล์อย่างไรโดยทำให้ความสูงเท่ากับ 0

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    if (findIndex! % 2 == 0){
        // Even index, show cell
        return CGSize(width: screenWidth, height: 246)
    }
    else {
        return CGSize(width: screenWidth, height: 0)
    }
}

1

ตรวจสอบให้แน่ใจว่าคุณใส่สิ่งนี้ไว้ใน viewDidLoad ()

collectionView.delegate = self

0

เมื่อคืนฉันมีปัญหานี้ ในที่สุดก็แก้ไขได้ในเวลาเที่ยงคืนเมื่อฉันรู้ว่าเมธอด 'didSelectItemAtIndex' ไม่ได้ปิดด้วยวงเล็บปิด "}"

ฉันเพิ่มวงเล็บปิดที่ด้านล่างสุดของชั้นเรียนเมื่อถูกถามโดยข้อผิดพลาดในการคอมไพล์ ดังนั้นวิธีการทั้งหมดด้านล่าง 'didSelectItemAtIndex' จึงอยู่ในเมธอดนั้น

โพสต์ที่นี่เผื่อว่าใครจะเสียเวลา 4 ชั่วโมงในตอนเย็นนี้ :-(


0

ปัญหาของฉันคือฉันมีวัตถุ UICollectionViewDataSource ที่สร้างขึ้นเป็นตัวแปรภายใน ดังนั้นหากคุณเริ่มต้นออบเจ็กต์ dataSource ด้วยตนเองในโค้ดอย่าลืมเก็บไว้เป็นตัวแปรส่วนกลาง


0

ใช้วิธีนี้

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

}

แทน

private func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

}


-12

สำหรับฉัน (ใน Swift 3.1) วิธีนี้จะต้องประกาศต่อสาธารณะดังนี้:

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

อย่าลืมที่จะทำให้มันสาธารณะ


publicคือสิ่งที่คุณใช้เพื่อทำให้โค้ดของคุณสามารถเข้าถึงได้ระหว่างเฟรมเวิร์กและโมดูล
ScottyBlades
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.