要让它完全按照你的意愿工作是很困难的。
自动布局会进行多次“通过”以尝试满足布局要求。但是,想想它必须做什么:
- 设置两个标签的文本
- “leftLabel”需要换行吗?
- “rightLabel”需要换行吗?
- 如果“leftLabel”换行了,“rightLabel”还需要换行吗?
- 反之亦然?
并且,在该过程中的什么时候可以确定两个标签最终都会换行,因此将每个标签设为宽度的 50%?请记住,单元格宽度会因设备和方向而异?
您可能想要查看您希望显示的实际数据,并考虑它的实际外观。 “正确的细节单元”设计最终可能不是最好的布局。
也就是说 - 这是一个可能适合您的自定义单元格。它需要大量的边缘测试来查看是否有任何尺寸被丢弃(例如,very 长字符串和/或字符串长度之间的非常大的差异):
class MyRightDetailCell: UITableViewCell {
var myTextLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.numberOfLines = 0
v.textAlignment = .left
v.font = UIFont.systemFont(ofSize: 17.0)
v.textColor = .black
v.setContentHuggingPriority(.required, for: .horizontal)
v.setContentHuggingPriority(.required, for: .vertical)
v.setContentCompressionResistancePriority(.required, for: .horizontal)
v.setContentCompressionResistancePriority(.required, for: .vertical)
return v
}()
var myDetailTextLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.numberOfLines = 0
v.textAlignment = .right
v.font = UIFont.systemFont(ofSize: 17.0)
v.textColor = .darkGray
v.setContentHuggingPriority(.required, for: .horizontal)
v.setContentHuggingPriority(.required, for: .vertical)
v.setContentCompressionResistancePriority(.required, for: .horizontal)
v.setContentCompressionResistancePriority(.required, for: .vertical)
return v
}()
var theStackView: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = false
v.axis = .horizontal
v.alignment = .top
v.distribution = .fill
v.spacing = 8
v.setContentHuggingPriority(.required, for: .vertical)
v.setContentCompressionResistancePriority(.required, for: .vertical)
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()
}
func commonInit() -> Void {
contentView.addSubview(theStackView)
theStackView.addArrangedSubview(myTextLabel)
theStackView.addArrangedSubview(myDetailTextLabel)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
theStackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
theStackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
theStackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
theStackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
])
}
}
class RightDetailTableViewController: UITableViewController {
var strings = [
("Some Very Long Black Text That Doesn't Fit. Foo Bar Baz.", ""),
("A", "Short Text"),
("B Somewhat Much Longer Left Label Text.", "With long right label text."),
("Working Now?", "Some Very Long Grey Text (Three Lines?) That Doesn't Fit. Foo Bar Baz"),
("C", "Another Text"),
("D", "With Long Right Label Text That Will Need To Wrap."),
]
let cellID = "MYRDC"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(MyRightDetailCell.self, forCellReuseIdentifier: cellID)
// make 5 copies of the test data so we'll have plenty of rows
// for scrolling (to check cell re-use)
for _ in 1...5 {
strings.append(contentsOf: strings)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// due to the complexity of the cell, the layout is more reliable if the
// table is reloaded here - try it with and without this extra reloadData() call
tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return strings.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! MyRightDetailCell
cell.myTextLabel.text = strings[indexPath.row].0
cell.myDetailTextLabel.text = strings[indexPath.row].1
// if either label has no text (""), set it to hidden
// to remove the stack view's spacing
cell.myTextLabel.isHidden = (strings[indexPath.row].0 == "")
cell.myDetailTextLabel.isHidden = (strings[indexPath.row].1 == "")
// un-comment the next two lines to show label background colors
// to make it easy to see the label frames
//cell.myTextLabel.backgroundColor = .cyan
//cell.myDetailTextLabel.backgroundColor = .green
return cell
}
}
输出: