簡體   English   中英

iOS swift UICollectionView 在滾動超過第一個屏幕后失去單元格約束

[英]iOS swift UICollectionView loses cell constraints after scrolling past first screen full

我正在嘗試學習如何在 Swift iOS 應用程序中處理 UICollectionViews - 只是一個簡單的應用程序,它在單元格中顯示圖像和 label 25 次。 最初的不良約束阻止了 CollectionView 顯示任何內容,但一旦我解決了這些問題,CollectionView 似乎會按預期和預期顯示單元格。 我的 Layout 方法按預期顯示了所有 25 個項目的調試消息。

然后,一旦它通過了第 11 項,我就向下滾動,它似乎完全失去了它的布局,如下圖所示。 向上滾動,更奇怪的是,所有單元格都變成了全尺寸圖像。

模擬器中的示例

代碼沒有什么特別之處,尤其是布局——代碼如下:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if indexPath.item > 10 {
        // Limit number of debug messages
            print("view.bounds: \(view.bounds)")
            print("collectionView.bounds: \(collectionView.bounds)")
            print("collectionView.alignmentRectInsets: \(collectionView.alignmentRectInsets)")
            print("collectionView.contentInset: \(collectionView.contentInset)")
        }
        let width = view.bounds.width
        print("width[\(indexPath.item)]: \(width)")
        let cellDimension = (width / 2 ) - 15
        print("cellDimension[\(indexPath.item)]: \(cellDimension)")
        let returnSize = CGSize(width: cellDimension, height: cellDimension)
        print("returnSize[\(indexPath.item)]: \(returnSize)")
        return returnSize
    }

一旦超過第 11 項,調試器就會開始噴出大量消息:

2019-10-22 01:32:54.794032-0500 CollectionTest#1[13173:339022] The behavior of the UICollectionViewFlowLayout is not defined because:
2019-10-22 01:32:54.794203-0500 CollectionTest#1[13173:339022] the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
2019-10-22 01:32:54.794360-0500 CollectionTest#1[13173:339022] Please check the values returned by the delegate.
2019-10-22 01:32:54.794856-0500 CollectionTest#1[13173:339022] The relevant UICollectionViewFlowLayout instance is <UICollectionViewFlowLayout: 0x7fe4c1407750>, and it is attached to <UICollectionView: 0x7fe492819400; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; gestureRecognizers = <NSArray: 0x600000965050>; layer = <CALayer: 0x60000076efe0>; contentOffset: {0, 355}; contentSize: {414, 2512}; adjustedContentInset: {20, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fe4c1407750>.
2019-10-22 01:32:54.801289-0500 CollectionTest#1[13173:339022] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
This just goes on and on ... abbreviated for brevity.

問題是,細胞以前都很好。

附加代碼:

CollectionViewCell.swift


import UIKit


class CollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var cellImage: UIImageView!
    @IBOutlet weak var cellLabel: UILabel!


}


ViewController.swift


import UIKit


class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 25
    }


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
        cell.cellImage.image = UIImage(named: "file-35")
        cell.cellLabel.text = "cell# \(indexPath.item)"


        cell.layer.borderWidth = 0.5
        cell.layer.borderColor = UIColor.lightGray.cgColor
        cell.layer.cornerRadius = 10


        cell.backgroundColor = UIColor.black
        cell.cellImage.layer.cornerRadius = 10


        print("indexPath.item: \(indexPath.item)")
        print("view.bounds: \(view.bounds)")
        print("collectionView.bounds: \(collectionView.bounds)")
        print("collectionView.contentInset: \(collectionView.contentInset)")
        print("collectionView.alignmentRectInsets: \(collectionView.alignmentRectInsets)")


        print("layoutAttributesForItem: \(String(describing: collectionView.layoutAttributesForItem(at: indexPath)))")


        return cell
    }




    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        collectionView.delegate = self
        collectionView.dataSource = self
//        view.translatesAutoresizingMaskIntoConstraints = true
    }

順便說一句,使用哪個版本的運行時模擬器似乎沒有任何區別。

非常感謝任何幫助、指示、建議等,而我還有一些頭發要拔掉。 謝謝你。

嘗試將CollectionViewCellcellImageclipToBounds屬性設置為true ,即

class CollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var cellImage: UIImageView!

    override func awakeFromNib() {
        super.awakeFromNib()
        self.cellImage.clipsToBounds = true //here..
    }
    //rest of the code....
}

也可以在UI本身設置clipToBoundscellImage ,即

在此處輸入圖像描述

注意:將單元格布局的所有代碼移動到CollectionViewCell中,而不是在cellForItemAt中寫入所有內容。 這將使代碼不那么龐大和可讀。

感謝您的建議。 我發現一篇 Stack Overflow 文章將我推向了一個似乎有助於解決問題的方向。

我可能是錯的,但我的觀察告訴我,似乎並非所有單元格的大小都是從 Storyboard 值初始化的。 前十幾個這樣做,但是當集合視圖開始重用/回收單元時,它會丟失單元大小的跟蹤。 我嘗試在 cellForItemAt() 中設置單元格大小,但這會導致一些非常糟糕的遞歸問題。

使用調試器觀察,sizeForItemAt() 僅在最初被調用,而不是在開始重用單元格時調用,並且當單元格大小丟失時,各種不受歡迎的事情開始發生。

在 viewDidLoad() 中初始化單元格大小消除了大部分問題,即直到設備旋轉,然后在 iPhone 模擬器中為新布局調用 sizeForItemAt() ,但在 iPad 模擬器中沒有。

解決方案是檢查 viewDidLoad() 中的設備類型並計算每行所需的單元格數。 如果您希望在設備旋轉時每行有不同數量的單元格,那么簡單地設置布局的單元格大小並不能完全解決問題。

這似乎已經解決了這些問題,至少目前是這樣。

我只是有點擔心我遺漏了一些東西,因為 sizeForItemAt() function 沒有按預期調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM