Динамическая высота для UITableView на основе динамического представления коллекции - PullRequest
0 голосов
/ 04 января 2019

Я должен добавить UICollectionView внутри UITableViewCell. У collectionView может быть разное количество предметов. Так что collectionView должен правильно отрегулироваться внутри tableView.

Я реализовал это в моем проекте: https://github.com/vishalwaka/DynamicCollectionViewInsideTableViewCell

В моем случае высота ячейки не регулируется после установки высоты collectionView.

Как настроить collectionView на невозможность прокрутки, а также показать весь контент внутри tableviewcell.

Ответы [ 3 ]

0 голосов
/ 07 января 2019

Создайте collectionView внутри UITableViewCell с ограничениями Leading, Trailing, Top, Bottom, Height следующим образом:

enter image description here

Теперь в вашем tableViewCell классе создайте NSKeyValueObserver и добавьте его к свойство *1013* contentSize и присвойте изменения contentSize ограничению высоты collectionView.

class FormCollectionTableViewCell: UITableViewCell{

  var collectionViewObserver: NSKeyValueObservation?

  override func awakeFromNib() {
    super.awakeFromNib()
    addObserver()
  }

  override func layoutSubviews() {
        super.layoutSubviews()
        layoutIfNeeded()
  }

  func addObserver() {
       collectionViewObserver = collectionView.observe(\.contentSize, changeHandler: { [weak self] (collectionView, change) in
            self?.collectionView.invalidateIntrinsicContentSize()
            self?.collectionViewHrightConstarint.constant = collectionView.contentSize.height
            self?.layoutIfNeeded()
        })
    }
   deinit {
      collectionViewObserver = nil
   }
}

А в вашем классе viewController используйте следующий код:

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        tableView.reloadData()
}

Теперь ваше табличное представление будет иметь коллекционное представление с динамической высотой. Не забудьте отключить прокрутку UICollectionView и настроить ее поток.

0 голосов
/ 13 января 2019

После проверки вашего проекта я предлагаю вам использовать немного другой подход.

После обновления модели вы можете спросить макет представления коллекции, каким будет новый размер контента ( collectionViewLayout.collectionViewContentSize ). Затем вы обновляете константу ограничения высоты.

Итак, вы должны:

  1. обновить вашу модель
  2. перезагрузить строку
  3. попросить макет для его нового contentSize
  4. обновить константу ограничения высоты

Эта модификация в вашем проекте должна достичь этого:

// Remove the content size observing logic.

func configureForVehicle(_ vehicle: Vehicle, selectedHouseType: String) {
    self.vehicle = vehicle

    applianceCollectionView.reloadData()

    // Set the height constraint to the new value, found in the layout's content size info.
    // Since the model (self.vehicle) was already updated, the layout will return the new content size.
    // Because this is all happening while the cell is being reloaded, the cell will also resize properly.
    // You don't need to perform any other setNeedsLayout/layoutIfNeeded calls.
    self.applianceCollectionViewHeightConstraint.constant = applianceCollectionView.collectionViewLayout.collectionViewContentSize.height
}

Обратите внимание на комментарий о том, что не требуется никаких дополнительных вызовов для обновления макета. Только звоню tableView.reloadRows(at: [indexPath], with: .automatic) должно быть достаточно. Ненужные обновления макета могут привести к снижению производительности.


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

  1. Обновите модель для ячейки, не вызывая вызовов перезагрузки табличного представления.
  2. Перезагрузите представление коллекции в обновленной ячейке.
  3. Обновить ограничение по высоте так же, как указано выше.
  4. Используйте какой-нибудь обратный вызов для уведомления вашего табличного представления о том, что ячейка хочет обновить свою высоту.
  5. В режиме обратного вызова tableView.beginUpdates(); tableView.endUpdates(). Это заставляет tableView переупорядочивать свои ячейки и анимировать изменения высоты.

Из документации beginUpdates () :

Вы также можете использовать этот метод и метод endUpdates () для анимации изменения высоты строк без перезагрузки ячейки. Эта группа методов должна завершаться вызовом endUpdates ().

0 голосов
/ 04 января 2019

Создайте следующий подкласс collectionView:

class IntrinsicSizeCollectionView: UICollectionView {

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.setup()
}

override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
    super.init(frame: frame, collectionViewLayout: layout)

    self.setup()
}

override func layoutSubviews() {
    super.layoutSubviews()
    if !self.bounds.size.equalTo(self.intrinsicContentSize) {
        self.invalidateIntrinsicContentSize()
    }
}

override var intrinsicContentSize: CGSize {
    get {
        let intrinsicContentSize = self.contentSize
        return intrinsicContentSize
    }
}

func setup() {
    self.isScrollEnabled = false
    self.bounces = false
}

Добавьте collectionView к tableViewCell и установите его ограничения, ведущие, конечные, верхние, нижние к границам ячейки. Также установите внутренний размер как на скриншоте.

enter image description here

Размер tableViewCell должен быть установлен в UITableViewAutomaticdimension, а также в поле DataSource таблицы TableView должен быть указан оценочныйВысота для этой ячейки.

Это должно быть все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...