[英]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
}
順便說一句,使用哪個版本的運行時模擬器似乎沒有任何區別。
非常感謝任何幫助、指示、建議等,而我還有一些頭發要拔掉。 謝謝你。
嘗試將CollectionViewCell
內cellImage
的clipToBounds
屬性設置為true
,即
class CollectionViewCell: UICollectionViewCell {
@IBOutlet weak var cellImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
self.cellImage.clipsToBounds = true //here..
}
//rest of the code....
}
也可以在UI本身設置clipToBounds
的cellImage
,即
注意:將單元格布局的所有代碼移動到CollectionViewCell
中,而不是在cellForItemAt
中寫入所有內容。 這將使代碼不那么龐大和可讀。
感謝您的建議。 我發現一篇 Stack Overflow 文章將我推向了一個似乎有助於解決問題的方向。
我可能是錯的,但我的觀察告訴我,似乎並非所有單元格的大小都是從 Storyboard 值初始化的。 前十幾個這樣做,但是當集合視圖開始重用/回收單元時,它會丟失單元大小的跟蹤。 我嘗試在 cellForItemAt() 中設置單元格大小,但這會導致一些非常糟糕的遞歸問題。
使用調試器觀察,sizeForItemAt() 僅在最初被調用,而不是在開始重用單元格時調用,並且當單元格大小丟失時,各種不受歡迎的事情開始發生。
在 viewDidLoad() 中初始化單元格大小消除了大部分問題,即直到設備旋轉,然后在 iPhone 模擬器中為新布局調用 sizeForItemAt() ,但在 iPad 模擬器中沒有。
解決方案是檢查 viewDidLoad() 中的設備類型並計算每行所需的單元格數。 如果您希望在設備旋轉時每行有不同數量的單元格,那么簡單地設置布局的單元格大小並不能完全解決問題。
這似乎已經解決了這些問題,至少目前是這樣。
我只是有點擔心我遺漏了一些東西,因為 sizeForItemAt() function 沒有按預期調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.