具有自动调整大小的单元格(estimatedSize)和sectionHeadersPinToVisibleBounds的UICollectionView是精神

时间:2017-01-27 15:24:24

标签: ios iphone swift xcode uicollectionview

考虑以下情况。我有一个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

但是布局进入奇怪的状态,我到处都有毛刺,细胞相互重叠,标题有时不会粘住。

更新:

视图控制器和单元格的代码:

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
}

Animation of result

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

2 个答案:

答案 0 :(得分:4)

2017年WWDC更新:

我的同事在2017年WWDC上,他向UIKit的一位工程师询问了这个问题。工程师确认这个问题已被苹果公司知道,并且当时没有修复。

答案 1 :(得分:-1)

使用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
    }