Программно создавая расширяющийся UItableViewCell
У меня есть ячейка просмотра таблицы, которую я хочу развернуть и свернуть при нажатии. Все примеры, которые я нашел, основаны на раскадровке, и я пытаюсь сделать это программно. Сначала я думал создать подпредставление и ограничить его представлением содержимого, но когда я настраиваю высоту ячейки с помощью heightForRowAt
это также увеличивает размер представления контента (что имеет смысл). Любые мысли о том, как я должен идти по этому поводу?
3 ответа
Использовать вертикальный UIStackView
с видом снизу isHidden
установите в значение true, а затем нажмите (или что-то еще является триггером расширения) просто измените isHidden = false
, Я думаю, это будет проще всего, учитывая, как UIStackView
имеет дело с isHidden
, Другой подход состоит в том, чтобы установить ограничения автоматического размещения и изменить привязку высоты нижнего вида, установив NSLayoutConstraint
постоянная к 0.
В любом случае, какой бы метод выбора вы ни выбрали, вам нужно будет указать tableView обновить его отображение (из viewcontroller):
func refreshTableAfterCellExpansion() {
self.tableView.beginUpdates()
self.tableView.setNeedsDisplay()
self.tableView.endUpdates()
}
Например, проверьте следующий ТАК вопрос и его ответ.
Пример использования игровых площадок (один с UIStackView
другой использует тот же принцип):
import UIKit
import PlaygroundSupport
class ExpandableCellViewController: UITableViewController, ExpandableCellDelegate {
override func loadView() {
super.loadView()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
tableView.register(ExpandableCell.self, forCellReuseIdentifier: "expandableCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "expandableCell", for: indexPath) as! ExpandableCell
cell.delegate = self
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell {
cell.isExpanded = true
}
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell {
cell.isExpanded = false
}
}
func expandableCellLayoutChanged(_ expandableCell: ExpandableCell) {
refreshTableAfterCellExpansion()
}
func refreshTableAfterCellExpansion() {
self.tableView.beginUpdates()
self.tableView.setNeedsDisplay()
self.tableView.endUpdates()
}
}
protocol ExpandableCellDelegate: class {
func expandableCellLayoutChanged(_ expandableCell: ExpandableCell)
}
class ExpandableCell: UITableViewCell {
weak var delegate: ExpandableCellDelegate?
fileprivate let stack = UIStackView()
fileprivate let topView = UIView()
fileprivate let bottomView = UIView()
var isExpanded: Bool = false {
didSet {
bottomView.isHidden = !isExpanded
delegate?.expandableCellLayoutChanged(self)
}
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
contentView.addSubview(stack)
stack.addArrangedSubview(topView)
stack.addArrangedSubview(bottomView)
stack.translatesAutoresizingMaskIntoConstraints = false
topView.translatesAutoresizingMaskIntoConstraints = false
bottomView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stack.topAnchor.constraint(equalTo: contentView.topAnchor),
stack.leftAnchor.constraint(equalTo: contentView.leftAnchor),
stack.rightAnchor.constraint(equalTo: contentView.rightAnchor),
stack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
topView.heightAnchor.constraint(equalToConstant: 50),
bottomView.heightAnchor.constraint(equalToConstant: 30),
])
stack.axis = .vertical
stack.distribution = .fill
stack.alignment = .fill
stack.spacing = 0
topView.backgroundColor = .red
bottomView.backgroundColor = .blue
bottomView.isHidden = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = ExpandableCellViewController()
Я бы просто определил 2 типа ячеек и выбрал тот, который подходит для tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
Вы можете использовать флаг, чтобы указать, развернут ли конкретный раздел или строка, и использовать эти методы в UITableView:
reloadRows()
reloadSections()
И измените метод heightForRow, чтобы он возвращал нужную высоту в соответствии с флагом Если вы хотите иметь возможность расширять более одной строки за раз, вы можете использовать ViewModel для каждого элемента в вашем источнике данных и обновлять флаг в нем при вызове методов didSelectItemAt или didDeselectItemAt, а затем перезагружать строку или раздел с нужной анимацией.