Ответ 1
После значительного объема исследований, я думаю, что нашел решение с помощью этой замечательной статьи.
Ниже приведены шаги, необходимые для изменения размера ячейки:
В основном и подробном представлениях я изначально устанавливал метки в горизонтальном и вертикальном направлении. Этого недостаточно для самостоятельной калибровки клеток. Первое, что мне нужно - это настроить мой макет с использованием ограничений вертикального расстояния вместо простого выравнивания:
Кроме того, вы должны установить сопротивление вертикального сжатия основного контейнера 1000.
Детальный вид немного сложнее: помимо создания соответствующих вертикальных ограничений вам также необходимо играть со своими приоритетами, чтобы достичь желаемого эффекта:
- Высота контейнера Detail ограничена 44 баллами, но для того, чтобы сделать его необязательным, установите его приоритет 999 (согласно документам, все, что ниже "Требуется", будет считаться таковым).
- Внутри контейнера Detail установите ограничения по вертикальному расстоянию и дайте им приоритет 998.
Основная идея заключается в следующем:
- По умолчанию ячейка сбрасывается. Чтобы достичь этого, мы должны программно установить константу ограничения длины контейнера Detail равным 0. Поскольку его приоритет выше, чем вертикальные ограничения в представлении содержимого ячейки, последний будет игнорироваться, поэтому контейнер Detail будет скрыт.
- Когда мы выбираем ячейку, мы хотим ее расширить. Это означает, что вертикальные ограничения должны взять под контроль: мы устанавливаем ограничение на ограничение приоритета Detail Container на что-то низкое (я использовал 250), поэтому он будет проигнорирован в пользу ограничений в представлении контента.
Мне пришлось изменить подкласс UITableViewCell
для поддержки этих операций:
// `showDetails` is exposed to control, whether the cell should be expanded
var showsDetails = false {
didSet {
detailViewHeightConstraint.priority = showsDetails ? lowLayoutPriority : highLayoutPriority
}
}
override func awakeFromNib() {
super.awakeFromNib()
detailViewHeightConstraint.constant = 0
}
Чтобы вызвать поведение, мы должны переопределить tableView(_:didSelectRowAtIndexPath:)
:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
switch expandedIndexPath {
case .Some(_) where expandedIndexPath == indexPath:
expandedIndexPath = nil
case .Some(let expandedIndex) where expandedIndex != indexPath:
expandedIndexPath = nil
self.tableView(tableView, didSelectRowAtIndexPath: indexPath)
default:
expandedIndexPath = indexPath
}
}
Обратите внимание, что я ввел expandedIndexPath
для отслеживания нашего расширенного индекса:
var expandedIndexPath: NSIndexPath? {
didSet {
switch expandedIndexPath {
case .Some(let index):
tableView.reloadRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Automatic)
case .None:
tableView.reloadRowsAtIndexPaths([oldValue!], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
}
Настройка свойства приведет к тому, что представление таблицы перезагрузит соответствующие индексы, предоставив нам прекрасную возможность рассказать ячейке, если она должна расширяться:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExpandableTableViewCell
cell.mainTitle = viewModel.mainTitleForRow(indexPath.row)
cell.detailTitle = viewModel.detailTitleForRow(indexPath.row)
switch expandedIndexPath {
case .Some(let expandedIndexPath) where expandedIndexPath == indexPath:
cell.showsDetails = true
default:
cell.showsDetails = false
}
return cell
}
Последний шаг состоит в том, чтобы включить самоограничение в viewDidLoad()
:
override func viewDidLoad() {
super.viewDidLoad()
tableView.contentInset.top = statusbarHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 125
}
Вот результат:
Теперь ячейки корректно сортируют. Вы можете заметить, что анимация все еще немного странная, но исправление, которое не входит в сферу этого вопроса.
Заключение: это было намного сложнее, чем должно быть. 😀 Я действительно надеюсь увидеть некоторые улучшения в будущем.