UITableViewAutomaticDimension, похоже, не учитывает содержимое метки детализации. Как я могу это исправить? - PullRequest
0 голосов
/ 18 января 2020

Я много читал о том, как автоматически настроить высоту ячеек таблицы в соответствии с текстом в ячейке. Начиная с , , , и , , кажется, что UITableView.automaticDimension - это путь к go. И, видимо, он работает и с системными (то есть нестандартными) ячейками.

В моем табличном представлении я использую набор системных ячеек в стиле «Правая деталь» (обратите внимание, что это не мой пользовательский интерфейс). ячейка):

enter image description here

Я сделал так, чтобы на обеих метках были «Линии» 0 и «Разрыв строки» «Перенос слов» для включения переноса слов , Теперь в моей таблице V C я заполнил табличное представление некоторыми данными, разработанными, чтобы показать мою проблему:

var strings = [("Some Very Long Black Text That Doesn't Fit. Foo Bar Baz.", ""),
               ("A", "Short Text"),
               ("B", "Foo Bar"),
               ("Not working:", "Some Very Long Grey Text That Doesn't Fit. Foo Bar Baz"),
               ("C", "Another Text")]

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return strings.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
    cell?.textLabel?.text = strings[indexPath.row].0
    cell?.detailTextLabel?.text = strings[indexPath.row].1
    return cell!
}

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

Это результат:

enter image description here

Как видите, первый ряд корректно корректирует свою высоту в соответствии с меткой, но метка четвертого ряда переполняет его ячейку. Кажется, что табличное представление только пытается подогнать высоту строки к textLabel.text, вообще не учитывая текст в detailTextLabel.

Как я могу заставить табличное представление учитывать оба текста метки при вычислении высота ячейки?


Дополнительная попытка:

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

enter image description here

enter image description here

1 Ответ

4 голосов
/ 20 января 2020

Будет сложно заставить его работать точно так, как вы хотите.

Автоматическое размещение делает несколько "проходов", чтобы попытаться удовлетворить требования макета. Однако подумайте о том, что он должен делать:

  • Установить текст обеих меток
  • Нужно ли оборачивать "leftLabel"?
  • Нужно ли "rightLabel" обернуть?
  • Если «leftLabel» оборачивается, нужно ли обернуть «rightLabel»?
  • и наоборот?

И в какой момент можно ли определить, что обе метки обернутся, так что каждая из них должна составлять 50% ширины? Помните, что ширина ячейки будет варьироваться в зависимости от устройства и ориентации?

Вы можете захотеть посмотреть на фактические данные, которые вы ожидаете отображать, и подумать, как они будут на самом деле смотреть. «Правильная ячейка детализации» может не оказаться лучшим макетом.

Тем не менее, вот пользовательская ячейка, которая может работать для вас. Потребуется много тестов по краям, чтобы увидеть, будет ли сброшено какое-либо определение размера (например, по очень длинных строк и / или очень большим разницам между длинами строк):

class MyRightDetailCell: UITableViewCell {

    var myTextLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.numberOfLines = 0
        v.textAlignment = .left
        v.font = UIFont.systemFont(ofSize: 17.0)
        v.textColor = .black
        v.setContentHuggingPriority(.required, for: .horizontal)
        v.setContentHuggingPriority(.required, for: .vertical)
        v.setContentCompressionResistancePriority(.required, for: .horizontal)
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

    var myDetailTextLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.numberOfLines = 0
        v.textAlignment = .right
        v.font = UIFont.systemFont(ofSize: 17.0)
        v.textColor = .darkGray
        v.setContentHuggingPriority(.required, for: .horizontal)
        v.setContentHuggingPriority(.required, for: .vertical)
        v.setContentCompressionResistancePriority(.required, for: .horizontal)
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

    var theStackView: UIStackView = {
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .horizontal
        v.alignment = .top
        v.distribution = .fill
        v.spacing = 8
        v.setContentHuggingPriority(.required, for: .vertical)
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

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

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    func commonInit() -> Void {

        contentView.addSubview(theStackView)
        theStackView.addArrangedSubview(myTextLabel)
        theStackView.addArrangedSubview(myDetailTextLabel)

        let g = contentView.layoutMarginsGuide

        NSLayoutConstraint.activate([
            theStackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            theStackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
            theStackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            theStackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
        ])

    }

}

class RightDetailTableViewController: UITableViewController {

    var strings = [
        ("Some Very Long Black Text That Doesn't Fit. Foo Bar Baz.", ""),
        ("A", "Short Text"),
        ("B Somewhat Much Longer Left Label Text.", "With long right label text."),
        ("Working Now?", "Some Very Long Grey Text (Three Lines?) That Doesn't Fit. Foo Bar Baz"),
        ("C", "Another Text"),
        ("D", "With Long Right Label Text That Will Need To Wrap."),
    ]

    let cellID = "MYRDC"

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(MyRightDetailCell.self, forCellReuseIdentifier: cellID)

        // make 5 copies of the test data so we'll have plenty of rows
        // for scrolling (to check cell re-use)
        for _ in 1...5 {
            strings.append(contentsOf: strings)
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // due to the complexity of the cell, the layout is more reliable if the
        // table is reloaded here - try it with and without this extra reloadData() call
        tableView.reloadData()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return strings.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! MyRightDetailCell

        cell.myTextLabel.text = strings[indexPath.row].0
        cell.myDetailTextLabel.text = strings[indexPath.row].1

        // if either label has no text (""), set it to hidden
        // to remove the stack view's spacing
        cell.myTextLabel.isHidden = (strings[indexPath.row].0 == "")
        cell.myDetailTextLabel.isHidden = (strings[indexPath.row].1 == "")

        // un-comment the next two lines to show label background colors
        // to make it easy to see the label frames
        //cell.myTextLabel.backgroundColor = .cyan
        //cell.myDetailTextLabel.backgroundColor = .green

        return cell
    }

}

Выход:

enter image description here

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