UICollectionViewCell:自动版式-大小计算不正确(偏移量大约为10 pt)

时间:2018-09-27 11:36:59

标签: ios autolayout uikit uicollectionviewcell sizing

我有一组 UICollectionViewCell 子类,它们具有不同的布局(使用AutoLayout)。

由于“自定义单元格”功能已完全损坏,因此我在 DataSource 中手动计算大小。但是,我注意到无论单元格如何,计算出的大小都比实际值小10磅

这是我用来计算尺寸的代码:

public void func1()
{
    ...
    button.Tag = new ParametersWrapper(arg1, arg2);
}

void DeleteActionHandler(object s, EventArgs e)
{
   var args = (ParametersWrapper)((Button)sender).Tag;
}

请注意最后一行中的行,我必须添加10磅才能使其正常工作。

我所有的单元格都是该基类的子类,该基类设置了 let sizeCache = CellCache() // Size cache stores previously calculated values func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { if let cachedSize = sizeCache.sizeAtIndexPath(indexPath: indexPath) { return cachedSize // Return cached value if it exists } // Calculate the size if not found in the cache let cellClass = cellTypeAt(indexPath: indexPath) // Get the class type let cell = sizeCache.createCellOfTypeIfNeeded(cellType: cellClass) // Dequeue or instantiate a cell self.collectionView(collectionView, cell: cell, configureAt: indexPath) // Ask DataSource to configure this cell let fittingSize = CGSize(width: collectionView.bounds.width - 16, height: 0) // Set the padding to 16 cell.bounds = CGRect(origin: .zero, size: fittingSize) // Set cell's width var result = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) // Calculate cell's size using AutoLayout result.width = collectionView.bounds.width - 16 // Set the padding result.height = result.height + 10 // !!! Error - Add 10 pt to the result !!! sizeCache.setSize(size: result, at: indexPath) // Cache the result return result } 约束:

width

问题的示例:

正确的尺寸(添加10磅后) Correct sizing (after adding 10 pt

大小不正确(不增加10点) Incorrect sizing (without adding 10 pt)

此问题影响所有单元格。可能是它的根本原因?

更新:约束示例 这是我用来配置显示的视图的约束:

import UIKit
import SnapKit

class AutoSizingCellBase: UICollectionViewCell {
  override class var requiresConstraintBasedLayout: Bool {
    return true
  }

  private final var widthConstraint: Constraint?

  override func updateConstraints() {
    if widthConstraint == nil {
      if let window = window {
        let width = window.bounds.width - 16
        contentView.snp.makeConstraints { (make) in
          widthConstraint = make.width.equalTo(width).constraint
        }
      }
    }
    super.updateConstraints()
  }
}

这是一个非常复杂的示例,但是即使使用更简单的示例,该问题也可以重现:

  private func setupConstraints() {
    price.setContentCompressionResistancePriority(.required, for: .horizontal)
    disclosureIndicator.setContentCompressionResistancePriority(.required, for: .horizontal)
    disclosureIndicator.setContentCompressionResistancePriority(.required, for: .vertical)
    disclosureIndicator.setContentHuggingPriority(.required, for: .horizontal)
    disclosureIndicator.setContentHuggingPriority(.required, for: .vertical)

    title.snp.makeConstraints { (make) in
      make.leading.top.equalTo(contentView.layoutMarginsGuide)
      make.trailing.lessThanOrEqualTo(price.snp.leading).offset(-8)
    }

    subtitle.snp.makeConstraints { (make) in
      make.top.equalTo(title.snp.bottom).offset(8)
      make.leading.bottom.equalTo(contentView.layoutMarginsGuide)
    }

    disclosureIndicator.snp.makeConstraints { (make) in
      make.trailing.equalTo(contentView.layoutMarginsGuide)
      make.centerY.equalToSuperview()
    }

    price.snp.makeConstraints { (make) in
      make.trailing.equalTo(disclosureIndicator.snp.leading).offset(-8)
      make.centerY.equalToSuperview()
    }
  }

更新

在约束中添加偏移量可以解决此问题,而视图层次结构调试器仍显示“歧义布局”:

  private func setupConstraints() {
    button.snp.makeConstraints { (make) in
      make.width.equalToSuperview() // Button is a subview of the UIStackView
    }

    stack.snp.makeConstraints { (make) in
      make.edges.equalTo(contentView.layoutMarginsGuide)
      make.height.greaterThanOrEqualTo(150)
    }
  }

问题是subtitle.snp.makeConstraints { (make) in make.top.equalTo(title.snp.bottom).offset(8) make.leading.equalTo(contentView.layoutMarginsGuide) make.bottom.equalTo(contentView.layoutMarginsGuide).offset(-10) // Subtracted 10 } 的来源仍然开放。

更新3 似乎部分问题在于调整10

layoutMargins

UIView.appearance().layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) 删除上面的行后,尽管单元格的外观发生了变化,但尺寸计算变得正确了。 因此,我认为问题是由于某种原因,为调整大小而创建的像元与从AppDelegate出队的像元具有不同的插图。

Cells without insets

1 个答案:

答案 0 :(得分:0)

LayoutMargins对于UICollectionViewCell的计算方式,在添加到超级视图时以及不在视图层次结构中时都不同。

因为这一行:

UIView.appearance().layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

添加到超级视图的像元的边距与为调整大小而创建的像元的边距不同。因此有所不同。