【问题标题】:UICollectionView with autosizing cell (estimatedSize) and sectionHeadersPinToVisibleBounds goes mentalUICollectionView 具有自动调整单元格(estimatedSize)和 sectionHeadersPinToVisibleBounds 的精神
【发布时间】:2017-01-27 15:24:23
【问题描述】:

考虑以下情况。我有一个UICollectionView(在UICollectionViewController 内),它看起来与UITableView 几乎相同(我不使用UITalbeView 的原因是因为我在布局上有非数据视图,这是我不想要的管理和弄乱我的IndexPath)。 为了实现自动调整单元格大小,我设置了estimatedItemSize,如下所示:

layout.estimatedItemSize = CGSize(width: self.view.bounds.size.width, height: 72)

另外,在我的单元格中,我有布局属性:

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
    return layoutAttributes
}

因此,通过这样做,我得到了与 UITableView 一样的精确布局,并具有自动调整大小。而且效果很好。

现在,我正在尝试添加标题并将其固定在滚动到该部分的顶部,如下所示:

layout.sectionHeadersPinToVisibleBounds = false

但是布局进入了奇怪的状态,我到处都有小故障,单元格相互重叠,并且标题有时不粘。

更新:

view controller和cell的代码:

class ViewController: UICollectionViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
    layout.sectionHeadersPinToVisibleBounds = true
    layout.estimatedItemSize = CGSize(width: collectionView?.bounds.size.width ?? 0, height: 36) // enables dynamic height
}

override func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 10
}

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

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell =  collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
    cell.heightConstraint.constant = CGFloat(indexPath.row * 10 % 100) + 10 // Random constraint to make dynamic height work

    return cell
}

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    return collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header", for: indexPath)
}

class CustomCell : UICollectionViewCell {
let identifier = "CustomCell"

@IBOutlet weak var rectangle: UIView!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!

override func awakeFromNib() {
    translatesAutoresizingMaskIntoConstraints = false
}

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
    return layoutAttributes
}

视频滞后详情:https://vimeo.com/203284395

【问题讨论】:

  • 添加一些图片以供参考将有助于我们可视化您遇到的问题
  • 能否附上截图?
  • 我没有答案,但部分问题可能是您基于self.view.bounds.size.width 设置layout.estimatedItemSize。如果您使用自动布局,那么width 有效的地方是违反直觉的。你所做的基本上是递归的:你根据width 设置一些东西,然后导致视图被调整大小,这导致width 发生变化。尝试删除该循环依赖。
  • 不,这是不对的。边界宽度与单元格布局无关。布局只影响单元格的大小和位置,而不影响集合视图本身的大小和位置。另外, self.view 是这里的集合视图的超级视图,所以根本不重要。它只是一个常数。
  • @PavelGatilov 添加您的 UI 图像和一些代码工作您所拥有的,以便我们可以准确估计需求并为您提供最佳答案,否则答案将是假设。

标签: ios iphone swift xcode uicollectionview


【解决方案1】:

WWDC 2017 更新:

我的同事在 WWDC 2017 上,他向一位 UIKit 工程师询问了这个问题。工程师确认这个问题是 Apple 已知的 bug,目前还没有修复。

【讨论】:

  • 这个有什么新东西吗?
【解决方案2】:

使用UICollectionViewDelegateFlowLayout 方法。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
        //Calculate your Dynamic Size Here for Each Cell at SpecificIndexPath.
        //For Example You want your Cell Height to be dynamic with Respect to indexPath.row number
        let cellWidth = collectionView?.bounds.size.width
        //Now Simply return these CellWidth and Height, and you are Good to go.
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellIdentifier", for: indexPath)
        //You Can Pass TextField As Well as i have considered UITextView for now.
        let cellSize = self. calculateSize(cellTextView: cell.textView, cellText: yourArrayOfText[indexPath.row], withFixedWidth: cellWidth)
        return cellSize
    }

并且不要通过直接更改 Constraint.constant 来更改 Cell Height。而不是这个简单地使用 Above Delegate 方法来改变高度。更改单元约束可能会导致此类问题。

使用下面的方法得到你想要的尺寸。

   func calculateSize(cellTextView: UITextView, cellText: String, withFixedWidth: CGFloat) -> CGSize {
            let textView = UITextView()
            textView.text = cellText
            textView.frame = cellTextView.frame
            textView.font = cellTextView.font
            textView.tag = cellTextView.tag
            let fixedWidth = withFixedWidth
            textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
            var newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
            return newSize
        }

使用 Bellow 方法计算图像大小。

//Method to Calculate ImageSize.
func calculateImageSize(image: UIImage) -> CGSize {
        var newSize = image.size
        if newSize.width > (ChatView.maxWidth - 70) {
            newSize.width = ChatView.maxWidth - 70
            newSize.height = ChatView.maxWidth - 70
        }
        if newSize.height < 60 {
            newSize.height = 60
            newSize.width = 60
        }
        return newSize
    }

【讨论】:

  • 好的。你不明白。约束只代表逻辑的一部分。它可以由任何动态的东西驱动,比如标签或图像中的文本数量等。
  • 所以你想改变 Cell with Respect 的大小到里面的文字??
  • 不一定是文本,但是是的,背后的想法是根据内部内容的大小更改单元格大小。当我添加粘贴标题时,一切都出错了。
  • 现在检查我的答案。我已经制定了一种方法来获取 TextView 相对于文本的大小。逻辑是创建一个空单元格并将 Cell 的 textView 沿文本和宽度传递给方法。现在您可以创建一个新的 textView 并将字体大小、字体类型分配给单元格的 textView 到这个新的 textView 并计算高度。现在只需将该高度和固定宽度返回给 UICollectionViewDelegateFlowLayout 方法。您现在将了解如何执行此操作。
  • 我已经附上了计算图像大小的方法。
猜你喜欢
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
  • 2015-02-26
  • 1970-01-01
相关资源
最近更新 更多