为啥 UIStackView 中的 UILabel 在重用时会失去高度?
Posted
技术标签:
【中文标题】为啥 UIStackView 中的 UILabel 在重用时会失去高度?【英文标题】: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()
【问题讨论】:
【参考方案1】:几件事...
不要在cell
或其.contentView
上设置.translatesAutoresizingMaskIntoConstraints
您正在为堆栈视图设置leading
和trailing
约束,因此无需设置其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
结果:
并且,在滚动之后,您可以看到它们被重复使用:
【讨论】:
以上是关于为啥 UIStackView 中的 UILabel 在重用时会失去高度?的主要内容,如果未能解决你的问题,请参考以下文章
UIStackView 中的 UILabel 中的 CAGradientLayer
将 UIStackView 中的 UILabel 背景更改为渐变色