【问题标题】:CollectionView sizeForItemAtIndexPath never calledCollectionView sizeForItemAtIndexPath 从未调用过
【发布时间】:2016-12-30 15:42:46
【问题描述】:

这快把我逼疯了!我有一个 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) 
    }

【问题讨论】:

    标签: ios


    【解决方案1】:

    您需要在类声明中指定实现协议UICollectionViewDelegateFlowLayout。

    class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

    【讨论】:

    • 我这样做了,但它仍然没有被调用。 :(
    • 在没有流布局委托的情况下尝试使用 sizeForItemAt 时我没有收到错误消息,这很烦人。只是浪费了 2 个小时的调试时间:/
    【解决方案2】:

    我遇到了同样的问题。帮助我的一件事是在 collectionView 大小检查器“无”下为单元格大小设置“估计大小”。

    【讨论】:

    • 你拯救了我的一天,哥们,你是英雄
    • 不知何故,关于使用sizeForItemAt 的所有其他帖子上的所有其他答案都没有提到这一点。非常有用。
    • 这太疯狂了!!!!我在 10.3.1 iOS 版本的 iPhone 5 模拟器上进行了测试,并调用了该方法。在 iPhone 5s 模拟器上使用 10.3.1 版本方法不会被调用!!!我将估计大小更改为无。它开始在 iPhone 5s 上被调用。 WT WT WT
    • 非常感谢!我使用自定义sizeForItemAt 的集合视图一直运行良好,直到 Xcode 11.4 突然单元格的宽度错误。尝试了一堆东西,这终于奏效了。
    • 谢谢! Apple 将这样的小事情变得极其复杂,这既令人沮丧又令人愤怒,我们都必须在这里讨论。
    【解决方案3】:

    在 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

    【讨论】:

    • 像 UICollectionViewController 一样遵守UICollectionViewDelegate 是多余的。
    • @VanDuTran 声明它是必需的并不是多余的,因为不需要作为 UICollectionViewController...
    • 我认为你的意思是一个非集合视图,Viewcontroller 可以是 UICollectionViewDelegate。
    • UICollectionViewDelegateFlowLayout 继承自 UICollectionViewDelegate 所以只需实现 UICollectionViewDelegateFlowLayout
    【解决方案4】:

    斯威夫特 5

    所有这些步骤都是必需的:

    1. 符合 UICollectionViewDelegateFlowLayout
    2. 和UICollectionViewDelegate, UICollectionViewDataSource
    3. 在 viewDidLoad 中设置这些:collectionView.delegate = self 和 collectionView.dataSource = self
    4. 在 Interface Builder 中将 Estimate Size 设置为 None
    5. 确保以下方法具有 sizeForItemAt 而不是 sizeForItemAtIndexPath

    作为:

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

    【讨论】:

    • 估计大小为无 - 节省我的一天!
    【解决方案5】:

    斯威夫特 3

    要设置 UICollectionView 的 Cell Size,您需要创建和自定义 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 {
    
    }
    

    【讨论】:

    • 这有什么帮助?
    • Almas,这将有助于设置 UICollectionViewCell 的自定义单元格大小...有变量 cellWidth 和 cellHeight,您可以定义自己的值...以及“layout.sectionInset”, “layout.minimumLineSpacing”和“layout.minimumInteritemSpacing”,这些变量对 UICollectionViewCell 大小也很重要。
    • 这仅适用于所有单元格大小相同的情况。以下答案是正确答案
    • 这是为了改变 UICollectionView 的大小,而不是视图内的单元格
    • 这不是为什么不调用委托方法的答案
    【解决方案6】:

    第一课需要确认UICollectionViewDelegateFlowLayout。然后你需要在viewDidLoad()中编写如下代码:

    //告诉UICollectionView使用你的UIViewController的 UICollectionViewDelegateFlowLayout方法

    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
    

    会被调用,你可以在这个方法中设置大小。

    【讨论】:

      【解决方案7】:

      如果没有答案,你需要检查三件事:

      1. 实现 FlowLayout 委托: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. 在 UICollectionView 的 Inspect 元素中选择 Estimate size = None。

      【讨论】:

        【解决方案8】:

        我遇到了同样的问题,没有什么可以解决的。我有一个黄色警告说要让它私有,因为它接近由 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)
            }
        }
        

        【讨论】:

          【解决方案9】:

          确保将其放入 viewDidLoad()

          collectionView.delegate = self
          

          【讨论】:

            【解决方案10】:

            我昨晚遇到了这个问题。终于在午夜解决了它,当我意识到 'didSelectItemAtIndex' 方法没有用闭括号“}”关闭时

            当编译错误询问时,我在类的最底部添加了一个闭括号。所以实际上“didSelectItemAtIndex”下面的所有方法都在该方法中。

            在这里发帖以防万一其他人在这个晚上浪费了 4 个小时 :-(

            【讨论】:

              【解决方案11】:

              只需添加:UICollectionViewDelegateFlowLayout

              class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}
              

              【讨论】:

                【解决方案12】:

                会不会布局错了:UICollectionViewLayout,其实这个布局应该是UICollectionViewFlowLayout这样的

                【讨论】:

                  【解决方案13】:

                  我设法通过调用解决了同样的问题

                  collectionView.delegate = self
                  

                  之前

                  collectionView.dataSource = self
                  

                  我有静态项目,从不重新加载数据。 显然设置dataSource会触发集合数据的同步加载,所以如果此时没有设置delegate,那么sizeForItemAtIndexPath永远不会被调用(除非reloadData稍后被调用)。

                  【讨论】:

                    【解决方案14】:

                    使用这个方法

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

                    代替

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

                    【讨论】:

                      【解决方案15】:

                      别忘了使用 UICollectionViewDelegateFlowLayout。在 xib/storyboard 中设置间距,并使用以下更新的函数调整单元格的大小以适应较新的 Swift 版本。编码快乐!!

                         @objc(collectionView:layout:sizeForItemAtIndexPath:)
                      func collectionView(_ collectionView: UICollectionView,
                                          layout collectionViewLayout: UICollectionViewLayout,
                                          sizeForItemAt indexPath: IndexPath) -> CGSize {
                          let numberOfItemsPerRow:CGFloat = 5
                          
                          if let collection = self.collectionView {
                              let width = collection.bounds.width / numberOfItemsPerRow
                              
                              return CGSize(width: width, height: 36)
                          }else{
                              return CGSize(width: 0, height: 0)
                          }
                      }
                      

                      【讨论】:

                        【解决方案16】:

                        如果您使用的是autolayout,请确保设置了collectionView.translatesAutoresizingMaskIntoConstraints = false。

                        【讨论】:

                          【解决方案17】:

                          对我来说(在 Swift 3.1 中)该方法必须像这样声明为 public:

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

                          别忘了将其设为公开。

                          【讨论】:

                          • public 是您用来使您的代码在框架和模块之间可访问的工具。
                          猜你喜欢
                          • 2017-11-13
                          • 2012-12-31
                          • 1970-01-01
                          • 2020-01-26
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多