UICollectionView 中重叠的单元格

Posted

技术标签:

【中文标题】UICollectionView 中重叠的单元格【英文标题】:Cells overlapping in UICollectionView 【发布时间】:2018-03-09 18:46:28 【问题描述】:

我正在使用动态大小的单元格在 UICollectionView 中向自定义 API 显示 Web 请求的结果。但是,当我在获取数据后调用 reloadSections 时,许多单元格显示重叠。

随着视图的滚动,单元格会显示在适当的位置。

我已经找到了在我的网络请求的完成块中调用 reloadSections 的错误。使用硬编码文本,集合视图可以正确显示初始布局。如果在完成块中调用 reloadSections,则会发生错误。下面是相关代码:

override func viewDidLoad() 
    super.viewDidLoad()

    collectionView.register(UINib.init(nibName: "ExhibitionsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ExhibitionsCollectionViewCell")
    layout.estimatedItemSize = CGSize(width: 1, height: 1)

    collectionView.dataSource = exhibitionsDataSource
    collectionView.delegate = self

    store.fetchExhibitions 
        (exhibitionsResult) -> Void in

        switch exhibitionsResult 
        case let .success(exhibitions):
            print("Successfully found \(exhibitions.count) exhibitions.")
            if exhibitions.first != nil 
                self.exhibitionsDataSource.exhibitions = exhibitions
            
        case let .failure(error):
            print("Error fetching exhibitions: \(error)")
            self.exhibitionsDataSource.exhibitions.removeAll()
        
        // this is the line that produces the erroneous layout
        self.collectionView.reloadSections(IndexSet(integer: 0))
    


发出网络请求的代码:

func fetchExhibitions(completion: @escaping (ExhibitionsResult) -> Void) 

    let url = WebAPI.exhibitionsURL
    let request = URLRequest(url: url)
    let task = session.dataTask(with: request) 
        (data, response, error) -> Void in

        let result = self.processExhibitionsRequest(data: data, error: error)
        OperationQueue.main.addOperation 
            completion(result)
        

    

    task.resume()

如果有任何其他代码有助于回答这个问题,请告诉我。

更新:我通过实现 UICollectionViewDelegateFlowLayout 的以下委托方法解决了这个问题

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

    let cell = collectionView.cellForItem(at: indexPath)
    let height = cell?.contentView.bounds.height ?? 1
    let width = cell?.contentView.bounds.width ?? 1


    return CGSize(width: width, height: height)

更新 2: 将我的假 Lorem Ipsum 数据换成从服务器实际检索到的数据后,问题再次出现。但是,我终于可以通过切换线路来解决问题

self.collectionView.reloadSections(IndexSet(integer: 0))

self.reloadData()

我认为 reloadSection(_:) 只是执行与 reloadData() 相同的操作,但对于选定的部分,文档似乎没有另外说明......但无论哪种方式现在都可以使用!

【问题讨论】:

仔细研究影响尺寸的所有因素。单元格 xib、流布局、容器 Xib、宽度/高度、边缘插图。如果不是这样,请熟悉队列和回收函数 PrepareForReuse()。事实上自动布局在放置之前计算。动画时间(默认为 0.25 秒)。 XCode 中 Xib 的大小与手机差异(不同手机/平板尺寸的布局是否不同)?他们都会为您提供缩小范围的指南。 【参考方案1】:

从该代码中我不确定原因,但可能尝试实现委托 UICollectionViewDelegateFlowLayout 提供的一些功能。

专注于功能

sizeForItemAtIndexPath

例子:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 
        return CGSizeMake(320, 500);
    

【讨论】:

这似乎解决了我的问题!自从我使用自动布局和自动调整单元格时,我就假设我不需要实现这个方法,但这个假设似乎是错误的。 虽然这确实解决了我最初的问题,但并没有最终解决手头的问题。从服务器检索数据时,我必须更改函数以重新加载数据。

以上是关于UICollectionView 中重叠的单元格的主要内容,如果未能解决你的问题,请参考以下文章

重叠的 UICollectionView 单元格

UICollectionView 中的单元格重叠

当我使用按钮增加单元格高度时,UICollectionView 单元格相互重叠

UICollectionView 单元格与 Header 重叠

以编程方式创建的 UICollectionView:滚动后单元格重叠

UICollectionView CellForItemAt 在滚动时被多次调用,导致单元格文本重叠