Как программно создать UITableViewCell с помощью SnapKit, который автоматически изменил его высоту? - PullRequest
1 голос
/ 30 апреля 2019

Что-то, казалось бы, простое оказалось действительно сложным. Я уже просмотрел несколько тем здесь и на SnapKit GitHub, но не смог решить мою проблему.

Я хочу получить UITableViewCell с меткой, расположенной посередине, скажем, 50 сверху и снизу ячейки.

Стоит отметить, что ячейка создается программно

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    self.addSubview(titleLabel)
    titleLabel.snp.makeConstraints { (make) -> Void in
        make.topMargin.equalToSuperview().offset(50.0)
        make.left.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue:10.0))
        make.bottomMargin.equalToSuperview().offset(50.0)

    }
}

В ViewController я попробовал оба подхода для автоматической высоты ячейки:

 extension EpisodeViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
  }
}

И

tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension

в viewDidLoad() метод

Что я получаю:

enter image description here

Каждая из этих трех ячеек должна быть заполнена «Test» - вместо этого она опустила метку под соответствующей ячейкой без изменения размера ячейки.

Пробовал много различных комбинаций, таких как:

1) Установка приоритета ограничения на 999 - без изменений

2) Добавление в contentView вместо self - вообще не отображается

3) Использование top вместо topMargin и т. Д. - без разницы

Не могли бы вы посоветовать мне, что не так с этим кодом, и каково общее эмпирическое правило при использовании SnapKit в программно созданных ячейках, которые должны автоматически изменять его высоту на основе ограничения?

Заранее спасибо

EDIT

UITableView Методы источника данных

extension EpisodeViewController: UITableViewDataSource {

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: EpisodeHeaderCell = tableView.dequeueReusableCell(for: indexPath)
    cell.viewModel = viewModel
    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}
func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

}

Ответы [ 3 ]

1 голос
/ 30 апреля 2019

UITableViewCell имеют contentView, который следует использовать для добавления пользовательских представлений

Так что попробуйте что-то вроде этого (я не проверял)

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    self.contentView.addSubview(titleLabel)

    titleLabel.snp.makeConstraints { (make) -> Void in
        // Changed from bottom to top
        make.top.equalTo(self.contentView.snp.top).offset(50)
        make.bottom.equalTo(self.contentView.snp.bottom).offset(50)
        make.left.equalTo(self.contentView.snp.left)
        make.right.equalTo(self.contentView.snp.right)
    }
}
1 голос
/ 30 апреля 2019
    label.snp.makeConstraints {
        $0.left.equalToSuperview().offset(10)
        $0.right.equalToSuperview().offset(-10)
        $0.top.equalToSuperview().offset(50)
        $0.bottom.equalToSuperview().offset(-50)
    }

Вот весь код файла viewController.swift.

class TestCell: UITableViewCell {
    static let identifier: String = "test_cell_identifier"

    var label: UILabel!

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.configure()
    }

    func configure() {
        label = UILabel(frame: .zero)
        self.contentView.addSubview(label)
        label.snp.makeConstraints {
            $0.left.equalToSuperview().offset(10)
            $0.right.equalToSuperview().offset(-10)
            $0.top.equalToSuperview().offset(50)
            $0.bottom.equalToSuperview().offset(-50)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class ViewController: UIViewController {
    var data: [String] = [
        "Test1",
        "Test2",
        "Test3"
    ]

    var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView = UITableView(frame: .zero)
        self.view.addSubview(tableView)
        tableView.snp.makeConstraints {
            $0.edges.equalToSuperview()
        }
        tableView.register(TestCell.self, forCellReuseIdentifier: TestCell.identifier)
        tableView.dataSource = self
        tableView.delegate = self

        tableView.estimatedRowHeight = 100
    }
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: TestCell.identifier, for: indexPath) as! TestCell
        cell.label.text = data[indexPath.item]
        return cell
    }
}
0 голосов
/ 30 апреля 2019

Я не использовал snapkit, но подход должен быть похожим. Вот как это можно сделать:

Первый набор размеров для автоматического:

self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = UITableView.automaticDimension

Тогда в вашей функции heightForRow;

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

Пользовательский UITableViewCell только с одной меткой:

class CustomCell: UITableViewCell {

var label: String? {
    didSet {
        answerLabel.text = label!
    }
}

private let customContentView = UIView()

private let answerLabel = UILabel()

// MARK: Initalizers
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    self.backgroundColor = UIColor(red:0.97, green:0.97, blue:0.97, alpha:1.0)

    self.selectionStyle = .none

    customContentView.translatesAutoresizingMaskIntoConstraints = false
    customContentView.backgroundColor = UIColor.white
    addSubview(customContentView)
    customContentView.anchor(self.topAnchor, left: self.leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)

    // configure label
    customContentView.addSubview(answerLabel)
    answerLabel.translatesAutoresizingMaskIntoConstraints = false
    answerLabel.leftAnchor.constraint(equalTo: customContentView.leftAnchor,constant: 5).isActive = true
    answerLabel.topAnchor.constraint(equalTo: customContentView.topAnchor,constant: 5).isActive = true
    answerLabel.rightAnchor.constraint(equalTo: customContentView.rightAnchor).isActive = true
    answerLabel.bottomAnchor.constraint(equalTo: customContentView.bottomAnchor, constant: -5).isActive = true
    answerLabel.numberOfLines = 0
    answerLabel.font = //YOUR FONT HERE
    answerLabel.textColor = UIColor(red:0.32, green:0.36, blue:0.36, alpha:1.0)

}
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

И наконец;

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: CustomCell = tableView.dequeueReusableCell(withIdentifier: cellId) as? CustomCell ??
        CustomCell(style: .default, reuseIdentifier: cellId)
    cell.label = "Title"

    return cell
}
...