StackView内的一些标签最初被截断,但在滚动时完美显示

问题描述 投票:0回答:2

出于某些要求,我尝试在TableView的单元格方法中尝试使用新的StackView

某些背景-我有一个TableView,它的单元格里面有一个stackViewstackView可以具有多种视图类型,但是为了简单起见,我现在使用labels。我创建了一个自定义的XIB(LabelInfoView),它具有3个水平标签。它以键值对组合的形式显示数据。标签可以是多行

enter image description here

现在我要在stackView单元格内的tableView内添加其中的6个

我已设置内容拥抱内容压缩抵抗优先级

对于名为Label的标签,>

enter image description here

对于名为分隔符

的标签>

enter image description here

对于名为Info

的标签”

enter image description here

问题-第一次加载表时,某些(并非全部)标签被随机顺序甚至是随机单元格截断(例如,第一个单元格的第三个标签视图被截断,第二个单元格的第一个,第二个和第二个这样,完全是随机的。即使在多个应用程序之间也没有固定的顺序)

enter image description here

(在第一个tableView的单元格中注意第5个labelView)

现在,当我将单元格从队列中移出时,滚动时,当我的第一个单元格进入屏幕,然后又回到屏幕上时,将称为prepareForReuse()

  cellsStackView.removeAllArrangedSubviews()
  setupCard()

我首先删除stackView内部的所有子视图,然后再次添加它们。这次,在调用方法之后,将正确加载stackView。

enter image description here

我尝试了很多事情,例如调整优先级和内容,但到目前为止没有任何效果!

我正在为某些要求在TableView的单元格方法中尝试新的StackView某些背景-我有一个TableView,并且它的单元格中有一个stackView。该stackView可以有多个...

这里是使用仅代码而不是自定义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

因为我同时将numberOfLinesleftLabel都设置为rightLabel设置为0

,所以自动布局引擎无法确定标签应多行显示,即标签需要宽度约束
。因此,我将leftLabel的宽度添加到<= Superview的宽度的50%
中。然后终于奏效了
ios swift uitableview autolayout uistackview
2个回答
1
投票

这里是使用仅代码而不是自定义XIB的示例。


1
投票

因为我同时将numberOfLinesleftLabel都设置为rightLabel设置为0

,所以自动布局引擎无法确定标签应多行显示,即标签需要宽度约束
© www.soinside.com 2019 - 2024. All rights reserved.