UICollectionViewCell: AutoLayout - неверный расчет размера (смещение точно на 10 пт) - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть набор UICollectionViewCell подклассов с различным макетом (с использованием AutoLayout).

Поскольку функция «Self Sizing Cells» полностью нарушена, я вычисляю размер вручную в DataSource .Однако я заметил, что вычисленный размер ровно на 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
  }

Обратите внимание на строку в конце, где Я должен добавить 10 pt , чтобы она заработала.

Все мои ячейки являются подклассами этого базового класса, который устанавливает width ограничение:

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()
  }
}

Примеры выпуска:

Правильный размер (после добавления 10 пт) Correct sizing (after adding 10 pt

Неправильный размер (без добавления 10 пт) Incorrect sizing (without adding 10 pt)

Эта проблема затрагивает все ячейки.Что может быть основной причиной этого?

Обновление: Пример ограничений Вот ограничения, которые я использую для настройки показанных представлений:

  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
}

Вопрос в том, откуда берется 10, все еще открыт.

Обновление 3 Кажется, чтоЧастично проблема заключается в корректировке layoutMargins:

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

. После того, как я удалил приведенную выше строку из AppDelegate, вычисления размера стали правильными, хотя внешний вид ячеек изменился.Поэтому я думаю, что проблема в том, что ячейки, созданные для определения размера, имеют иную вставку, нежели ячейки, снятые с UICollectionView.

Cells without insets

1 Ответ

0 голосов
/ 01 октября 2018

LayoutMargins рассчитываются по-разному для UICollectionViewCell при добавлении в суперпредставление и когда нет в иерархии представлений.

Из-за строки:

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

Ячейки добавляются вУ superview были другие поля, чем у ячеек, созданных для определения размеров.Отсюда и разница.

...