#ios #autolayout #uicollectionviewcell
#iOS #автоматическое описание #uicollectionviewcell
Вопрос:
В conentView collectionCell я хочу ограничить вертикальный вложенный просмотр разной высотой в соответствии с разными значениями, но проблема в том, что высота неожиданно изменяется, когда содержимое прокручивается с экрана, затем прокручивается обратно на экран:
Начальная и правильная высота представления:
Прокрутите экран, затем назад (высота просмотра изменяется по неизвестной причине):
Ниже приведен код макета:
let contentView = cell.contentView
let row = indexPath.row
//calculate view height: relativeHeight value
let cellHeight = cell.frame.height
var relativeHeight = 0.6 * cellHeight
let values = [112.0, 116.0, 86.0, 95.0, 67.0, 76.0, 34.0, 43.0, 24.0, 35.0, 47.0, 66.0, 66.0, 57.0, 36.0, 64.0, 23.0, 22.0, 23.0, 22.0, 22.0, 22.0, 20.0, 23.0]
let Δvalue = values.max()! - values.min()!
let value = values[row]
if Δvalue != 0 {
let different = value - values.min()!
let ratio = CGFloat(different / Δvalue)
relativeHeight = ratio * relativeHeight
}
if contentView.subviews.count == 0 {
//time label
let timeLabel = UILabel()
timeLabel.tag = 3
timeLabel.textColor = self.textColor
timeLabel.font = UIFont.boldSystemFont(ofSize: 13)
contentView.addSubview(timeLabel)
timeLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
timeLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4),
timeLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
])
//vertical view
let valueView = UIView()
valueView.tag = 1
valueView.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.382) //1-0.618
contentView.addSubview(valueView)
valueView.translatesAutoresizingMaskIntoConstraints = false
//valueView.constraints.forEach{ $0.isActive = false }
NSLayoutConstraint.activate([
valueView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
valueView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
valueView.bottomAnchor.constraint(equalTo: timeLabel.topAnchor, constant: -4),
valueView.heightAnchor.constraint(equalToConstant: relativeHeight)
])
//value label
let valueLabel = UILabel()
valueLabel.tag = 2
valueLabel.textColor = self.textColor
valueLabel.font = UIFont.systemFont(ofSize: 12)
contentView.addSubview(valueLabel)
valueLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
valueLabel.bottomAnchor.constraint(equalTo: valueView.topAnchor, constant: -4),
valueLabel.centerXAnchor.constraint(equalTo: valueView.centerXAnchor)
])
}
Как я могу решить такую проблему с ограничениями макета?
Заранее большое спасибо!
Комментарии:
1.
valueView.heightAnchor.constraint(equalToConstant: relativeHeight)
как вы вычисляетеrelativeHeight
? Также есть какая-либо особая причина для деактивации ограничений перед добавлением их в операторvalueView.constraints.forEach{ $0.isActive = false }
, сохраняете ли вы ссылку наvalueView
в ячейке? есть ли шанс не создавать его, если есть существующийvalueView
?2. Пожалуйста, ознакомьтесь с дополнением к вычислению относительной высоты. Я подумал, что, возможно, конфликт ограничений вызвал изменение высоты представления, поэтому я сначала пытаюсь деактивировать, а затем активировать. Каждая ячейка имеет свой собственный или независимый valueView, он не хранит ссылку, которая может использоваться другой ячейкой.
3. расчет для
relativeHeight
мне кажется, что все в порядке, поскольку вы выделяете новый экземплярvalueView
каждый раз, когда выполняется код, я думаю, в этом нет необходимостиvalueView.constraints.forEach{ $0.isActive = false }
. ОДИН БОЛЬШОЙ ВОПРОС, когда и где выполняется этот код? ЭтоcellForRow(:indexPath)
или какой-либо другой метод жизненного циклаUITableViewCell
? Таким образом будет сложно отлаживать, можете ли вы создать один пример проекта с проблемой и поделиться им на github, это будет здорово проверить дальше.4. Это в cellForRow (:indexPath) . Пожалуйста, загрузите код по адресу » github.com/steve880925/CollectionView-Bug »
Ответ №1:
Я думаю, проблема заключалась в том, что не было ссылки на valueView
или heightConstraint
, которую вы пытаетесь установить после выделения, проверки contentView.subviews.count == 0
. Способ, которым вы готовите иерархию представлений для UICollectionViewCell
, может вообще не быть хорошей практикой. При удалении из очереди повторно используемого представления необходимо учитывать все условия для установки динамических значений. Здесь не было никакого обработчика, если contentView.subviews.count == 0
сбой.
Исправление было выполнено с использованием подкласса UICollectionViewCell
для абстрагирования всех связанных с представлением задач внутри CollectionViewCell: UICollectionViewCell
. Я добавил одно свойство valueViewHeightConst
с начальным значением ограничения 0.0. Я устанавливаю точное значение после вычисления значения высоты для установки.
Также представлен один механизм кэширования, где вам не нужно вычислять relativeHeight
каждый раз, когда ячейка удаляется из очереди.
Пожалуйста, проверьте окончательный проект наhttps://github.com/sauvikapple/StackoverflowAnsToQ63743769.