Запрет UIStackView от сжатия UITableView - PullRequest
0 голосов
/ 22 июня 2019

Я добавляю UITableView в вертикальный UIStackView.Этот вертикальный UIStackView находится внутри UIScrollView.

Однако таблица не отображается, пока я не наложу на нее явное ограничение высоты, которое я явно не хочу делать.

Согласно этому вопросу и ответу UITableView не показанвнутри UIStackView это потому, что "stackview пытается сжать контент как можно больше"

Если я добавлю UILabel в StackView, он будет отображаться нормально.В UITableView есть что-то конкретное, что означает, что это не так.Я использую Xamarin и создаю UITableView в коде

this.recentlyOpenedPatientsTable = new UITableView()
{
    RowHeight = UITableView.AutomaticDimension,
    EstimatedRowHeight = 44.0f,
    AllowsMultipleSelectionDuringEditing = false,
    TranslatesAutoresizingMaskIntoConstraints = false,
    Editing = false,
    BackgroundColor = UIColor.Clear,
    TableFooterView = new UIView(),
    ScrollEnabled = false,
};   

UIScrollView закрепляется сверху, снизу, слева и справа от представления и работает нормально.Требуется высота, на которую я рассчитываю.

Я попробовал оба предложения в этом вопросе, и ни один из них не сработал.Мне кажется странным, что я не могу найти других, имеющих эту проблему.

Какие-либо другие предложения?

1 Ответ

1 голос
/ 24 июня 2019

Вот очень простой пример использования подкласса UITableView для автоматического изменения его высоты в зависимости от его содержимого.

Красные кнопки (в горизонтальном представлении стека) являются первыми упорядоченный подвид в вертикальном представлении стека.

Таблица следующая (зеленый фон для contentView ячеек, желтый фон для многострочной метки).

И последнееупорядоченный подвид представляет собой голубой фон UILabel:

enter image description here

Обратите внимание, что представление вертикального стека ограничено 40 пунктами от Top, Leading и Trailing, и не менее 40 пунктов от основания.Если вы добавите в таблицу достаточно строк, чтобы превысить доступную высоту, вам придется прокрутить, чтобы увидеть дополнительные строки.

//
//  TableInStackViewController.swift
//
//  Created by Don Mag on 6/24/19.
//

import UIKit

final class ContentSizedTableView: UITableView {

    override var contentSize:CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }

}

class TableInStackCell: UITableViewCell {

    let theLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .yellow
        v.textAlignment = .left
        v.numberOfLines = 0
        return v
    }()

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

        contentView.backgroundColor = .green

        contentView.addSubview(theLabel)

        NSLayoutConstraint.activate([

            theLabel.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor, constant: 0.0),
            theLabel.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor, constant: 0.0),
            theLabel.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor, constant: 0.0),
            theLabel.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor, constant: 0.0),

            ])

    }

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


}

class TableInStackViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    let theStackView: UIStackView = {
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .vertical
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 8
        return v
    }()

    let addButton: UIButton = {
        let v = UIButton()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.setTitle("Add a Row", for: .normal)
        v.backgroundColor = .red
        return v
    }()

    let deleteButton: UIButton = {
        let v = UIButton()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.setTitle("Delete a Row", for: .normal)
        v.backgroundColor = .red
        return v
    }()

    let buttonsStack: UIStackView = {
        let v = UIStackView()
        v.axis = .horizontal
        v.alignment = .fill
        v.distribution = .fillEqually
        v.spacing = 20
        return v
    }()

    let theTable: ContentSizedTableView = {
        let v = ContentSizedTableView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    let bottomLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .cyan
        v.textAlignment = .center
        v.numberOfLines = 0
        v.text = "This label is the last element in the stack view."
        // prevent label from being compressed when the table gets too tall
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

    var theTableData: [String] = [
        "Content Sized Table View",
        "This row shows that the cell heights will auto-size, based on the cell content (multi-line label in this case).",
        "Here is the 3rd default row",
    ]

    var minRows = 1

    let reuseID = "TableInStackCell"

    override func viewDidLoad() {
        super.viewDidLoad()

        minRows = theTableData.count

        view.addSubview(theStackView)

        NSLayoutConstraint.activate([

            // constrain stack view 40-pts from top, leading and trailing
            theStackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),
            theStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40.0),
            theStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40.0),

            // constrain stack view *at least* 40-pts from bottom
            theStackView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -40.0),

            ])

        buttonsStack.addArrangedSubview(addButton)
        buttonsStack.addArrangedSubview(deleteButton)

        theStackView.addArrangedSubview(buttonsStack)
        theStackView.addArrangedSubview(theTable)
        theStackView.addArrangedSubview(bottomLabel)

        theTable.delegate = self
        theTable.dataSource = self

        theTable.register(TableInStackCell.self, forCellReuseIdentifier: reuseID)

        addButton.addTarget(self, action: #selector(addRow), for: .touchUpInside)
        deleteButton.addTarget(self, action: #selector(deleteRow), for: .touchUpInside)

    }

    @objc func addRow() -> Void {
        // add a row to our data source
        let n = theTableData.count - minRows
        theTableData.append("Added Row: \(n + 1)")
        theTable.reloadData()
    }

    @objc func deleteRow() -> Void {
        // delete a row from our data source (keeping the original rows intact)
        let n = theTableData.count
        if n > minRows {
            theTableData.remove(at: n - 1)
            theTable.reloadData()
        }
    }

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

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseID, for: indexPath) as! TableInStackCell
        cell.theLabel.text = theTableData[indexPath.row]
        return cell
    }

}
...