Несколько ярлыков внутри StackView изначально усекаются, но при прокрутке выглядят идеально. - PullRequest
0 голосов
/ 18 октября 2019

Я пробовал новый StackView в подходе ячейки TableView для определенного требования

Некоторый фон - у меня есть TableView, а в его ячейке есть stackView внутри. Это stackView может иметь несколько типов представлений внутри него, но ради простоты я сейчас работаю с labels. Я создал пользовательский XIB (LabelInfoView), который имеет 3 метки по горизонтали. Он показывает данные в виде комбинации пары ключ-значение. Метки могут быть многострочными

enter image description here

Теперь я добавляю 6 из них в stackView, который присутствует внутри ячейки tableView

Я установил обнимание содержимого и сопротивление сжатию содержимого приоритеты

Для ярлыка с именем Метка

enter image description here

Для метки с именем Разделитель

enter image description here

Для метки с именем Информация

enter image description here

Проблема - При первой загрузке таблицы некоторые (не все) ярлыки обрезаются прислучайные порядки и даже для случайных ячеек (скажем, представление третьей метки первой ячейки становится усеченным, а первая и вторая - второй ячейки и т. д., абсолютно случайными. Нет фиксированных порядков даже между несколькими запусками приложений)1059 *

(Обратите внимание, 5-й labelView внутри ячейки первого tableView)

Теперь, когда я убираю ячейки с очереди, прокручивая, когда моя первая ячейка выходит из экрана, а затем, когда возвращается на экран, prepareForReuse() будет называться

  cellsStackView.removeAllArrangedSubviews()
  setupCard()

Сначала я удаляю все подпредставления внутри stackView и добавляю их снова. На этот раз, после вызова метода, stackView загружен правильно.

enter image description here

Я пробовал много вещей, таких как настройка приоритетов и прочее, нопока ничего не работает!

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Поскольку я устанавливал numberOfLines в 0 как для leftLabel, так и для rightLabel, механизм автоматической разметки не смог выяснить, в какой момент метка должна стать мульти-линии, т. е. для метки требовалось ограничение ширины . Итак, я добавил ширину leftLabel к <= 50% ширины суперпредставления </strong>. И тогда это, наконец, сработало

1 голос
/ 18 октября 2019

Вот пример использования только кода вместо пользовательской XIB.

Нет IBOutlet или ячеек прототипа, поэтому просто присвойте WorkTableViewController в качестве пользовательского класса для UITableViewController:

class MyThreeLabelView: UIView {

    let leftLabel: UILabel = {
        let v = UILabel()
        return v
    }()

    let sepLabel: UILabel = {
        let v = UILabel()
        return v
    }()

    let rightLabel: UILabel = {
        let v = UILabel()
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

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

    private func commonInit() {

        backgroundColor = .white

        [leftLabel, sepLabel, rightLabel].forEach {
            $0.font = UIFont.systemFont(ofSize: 16.0)
            $0.translatesAutoresizingMaskIntoConstraints = false
            addSubview($0)
        }

        // bold-italic font for left label
        leftLabel.font = leftLabel.font.boldItalic

        // we want left and separator labels to NOT compress or expand
        leftLabel.setContentHuggingPriority(.required, for: .horizontal)
        leftLabel.setContentHuggingPriority(.required, for: .vertical)
        leftLabel.setContentCompressionResistancePriority(.required, for: .horizontal)

        sepLabel.setContentHuggingPriority(.required, for: .horizontal)
        sepLabel.setContentHuggingPriority(.required, for: .vertical)
        sepLabel.setContentCompressionResistancePriority(.required, for: .horizontal)

        // right label should hug vertically
        rightLabel.setContentHuggingPriority(.required, for: .vertical)

        // right label can be mutliple lines
        rightLabel.numberOfLines = 0

        NSLayoutConstraint.activate([

            // constrain all 3 labels 10-pts from top, at least 10-pts from bottom
            leftLabel.topAnchor.constraint(equalTo: topAnchor, constant: 10.0),
            leftLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -10),

            sepLabel.topAnchor.constraint(equalTo: leftLabel.topAnchor, constant: 0.0),
            sepLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -10),

            rightLabel.topAnchor.constraint(equalTo: leftLabel.topAnchor, constant: 0.0),
            rightLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -10),

            // constrain left label 10-pts from leading edge
            leftLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10.0),

            // constrain separator label 10-pts from left label
            sepLabel.leadingAnchor.constraint(equalTo: leftLabel.trailingAnchor, constant: 10.0),

            // constrain right label 10-pts from separator label
            rightLabel.leadingAnchor.constraint(equalTo: sepLabel.trailingAnchor, constant: 10.0),

            // constrain right label 10-pts from trailing edge
            rightLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),

        ])

    }

}

class StackCell: UITableViewCell {

    let stackView: UIStackView = {
        let v = UIStackView()
        v.axis = .vertical
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 0
        v.translatesAutoresizingMaskIntoConstraints = false
        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()
    }

    override func prepareForReuse() {
        super.prepareForReuse()

        // remove all arrangedSubviews from stack view
        stackView.arrangedSubviews.forEach {
            $0.removeFromSuperview()
        }
    }

    func commonInit() -> Void {

        contentView.backgroundColor = .lightGray

        // add the stack view
        contentView.addSubview(stackView)

        // constrain 12-pts on all 4 sides
        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12.0),
            stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12.0),
            stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12.0),
            stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12.0),
        ])

    }

    func addLabels(_ labels: [String]) -> Void {
        labels.forEach {
            s in

            // instance of MyThreeLabelView
            let v = MyThreeLabelView()
            // for this example, left and separator labels don't change
            v.leftLabel.text = "Assigned To"
            v.sepLabel.text = "-"
            // assign right label text
            v.rightLabel.text = s
            // add MyThreeLabelView to the stack view
            stackView.addArrangedSubview(v)
        }
    }

}

class WorkTableViewController: UITableViewController {

    let reuseID = "StackCell"

    var theData: [[String]] = [[String]]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // make 8 sets of 6-rows of labels
        for i in 1...8 {
            let tmp: [String] = [
                "1) Row \(i)",
                "2) Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s",
                "3) Short text.",
                "4) Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s",
                "5) Short text.",
                "6) Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s",
            ]
            theData.append(tmp)
        }

        tableView.register(StackCell.self, forCellReuseIdentifier: reuseID)

    }

    // MARK: - Table view data source

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

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

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

        cell.addLabels(theData[indexPath.row])

        return cell
    }

}

// UIFont extension for bold / italic / boldItalic
// found here: https://stackoverflow.com/a/21777132/6257435
extension UIFont {
    var bold: UIFont {
        return with(.traitBold)
    } // bold

    var italic: UIFont {
        return with(.traitItalic)
    } // italic

    var boldItalic: UIFont {
        return with([.traitBold, .traitItalic])
    } // boldItalic

    func with(_ traits: UIFontDescriptor.SymbolicTraits...) -> UIFont {
        guard let descriptor = self.fontDescriptor.withSymbolicTraits(UIFontDescriptor.SymbolicTraits(traits).union(self.fontDescriptor.symbolicTraits)) else {
            return self
        }
        return UIFont(descriptor: descriptor, size: 0)
    }

    func without(_ traits: UIFontDescriptor.SymbolicTraits...) -> UIFont {
        guard let descriptor = self.fontDescriptor.withSymbolicTraits(self.fontDescriptor.symbolicTraits.subtracting(UIFontDescriptor.SymbolicTraits(traits))) else {
            return self
        }
        return UIFont(descriptor: descriptor, size: 0)
    }

} // extension

Результат:

enter image description here

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