【问题标题】:Why do UILabel inside UIStackView lose its height when reusing occurs?为什么 UIStackView 中的 UILabel 在重用时会失去高度?
【发布时间】:2020-01-08 15:00:35
【问题描述】:

当单元格被重用时,UIStackView 中的 UILabel 开始失去它们的大小。可能与什么有关。对于表格,单元格高度在 UITableView.automaticDimension 中设置。

我不明白这与重用有什么关系,因为我使用的是 prepareForReuse。

class SalesPointTableViewCell: UITableViewCell {

private var nameLabel = UILabel()

private var someView: UIStackView = {
    $0.distribution = .fill
    $0.translatesAutoresizingMaskIntoConstraints = false
    $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)

    return $0
}(UIStackView())

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    translatesAutoresizingMaskIntoConstraints = false
    contentView.translatesAutoresizingMaskIntoConstraints = false
    contentView.addSubview(nameLabel)
    contentView.addSubview(someView)
    nameLabel.snp.makeConstraints {
        $0.left.top.equalToSuperview()
    }
    someView.snp.makeConstraints {
        $0.left.right.width.equalToSuperview()
        $0.top.equalTo(nameLabel.snp.bottom)
    }
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
    super.prepareForReuse()
    nameLabel.text = nil
    someView.arrangedSubviews.forEach {$0.removeFromSuperview()}
}

func configure(name: String, points: [String]) {
    self.nameLabel.text = name
    points.forEach { pointName in
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.numberOfLines = 1
        label.text = pointName
        self.someView.addArrangedSubview(label)
        label.sizeToFit()
    }
}
}

【问题讨论】:

    标签: swift uitableview uilabel uistackview


    【解决方案1】:

    几件事...

    • 不要在cell 或其.contentView 上设置.translatesAutoresizingMaskIntoConstraints
    • 您正在为堆栈视图设置leadingtrailing 约束,因此无需设置其width
    • 您缺少bottom 约束

    试试这个:

    class SalesPointTableViewCell: UITableViewCell {
    
        private var nameLabel = UILabel()
    
        private var someView: UIStackView = {
    
            $0.distribution = .fill
    
            // add a little spacing between arranged subviews so we can see them
            $0.spacing = 4
    
            $0.translatesAutoresizingMaskIntoConstraints = false
            $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
    
            return $0
        }(UIStackView())
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            // no no no
            //translatesAutoresizingMaskIntoConstraints = false
    
            // no no no
            //contentView.translatesAutoresizingMaskIntoConstraints = false
    
            contentView.addSubview(nameLabel)
            contentView.addSubview(someView)
    
            nameLabel.snp.makeConstraints {
                $0.left.top.equalToSuperview()
            }
    
            // you're missing a bottom constraint
            //someView.snp.makeConstraints {
            //  $0.left.right.width.equalToSuperview()
            //  $0.top.equalTo(nameLabel.snp.bottom)
            //}
    
            someView.snp.makeConstraints {
                // costraining left and right, so no need for width
                //  $0.left.right.width.equalToSuperview()
                $0.left.right.equalToSuperview()
    
                $0.top.equalTo(nameLabel.snp.bottom)
    
                // need to add a bottom constraint
                $0.bottom.equalToSuperview()
            }
    
            // give nameLabel a cyan background to make it easy to see the frame
            nameLabel.backgroundColor = .cyan
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        override func prepareForReuse() {
            super.prepareForReuse()
            nameLabel.text = nil
            someView.arrangedSubviews.forEach {$0.removeFromSuperview()}
        }
    
        func configure(name: String, points: [String]) {
            self.nameLabel.text = name
            points.forEach { pointName in
                let label = UILabel()
                label.translatesAutoresizingMaskIntoConstraints = false
    
                // give labels a green background to make it easy to see the frames
                label.backgroundColor = .green
                label.textAlignment = .center
    
                label.numberOfLines = 1
                label.text = pointName
                self.someView.addArrangedSubview(label)
    
                // sizeToFit is not needed
                //label.sizeToFit()
            }
        }
    }
    
    class SalesTableViewController: UITableViewController {
    
        var theData: [[String]] = [[String]]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            tableView.register(SalesPointTableViewCell.self, forCellReuseIdentifier: "SPCell")
    
            // generate 50 "sales points"
            // each "sales point" will have 1, 2 or 3 labels
            for i in 1...50 {
                let n = Int.random(in: 1...3)
                var a: [String] = [String]()
                for j in 1...n {
                    a.append("Point: \(i) / \(j)")
                }
                theData.append(a)
            }
    
        }
    
        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: "SPCell", for: indexPath) as! SalesPointTableViewCell
    
            let a = theData[indexPath.row]
    
            cell.configure(name: "Test \(indexPath.row)", points: a)
    
            return cell
    
        }
    
    }
    

    结果:

    并且,在滚动之后,您可以看到它们被重复使用:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-04
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      相关资源
      最近更新 更多