我有一个"普通"风格UITableView。我将视图设置为表视图的tableViewHeader
。该表还显示了右侧的部分索引。
我的问题是如何插入标题视图的左右边缘,以便在iPhone X(横向)和表格视图的部分索引(如果有)上运行时考虑安全区域插入是一个)。
我创建了一个简单的测试应用程序,它添加了一些虚拟行,一个节头和节索引。
这是我使用UILabel创建简单标题视图的代码。我真正的应用程序不会使用标签,而是使用自定义视图。
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 30)
label.backgroundColor = .green
label.text = "This is a really long Table Header label to make sure it is working properly."
label.sizeToFit()
tableView.tableHeaderView = label
没有任何特殊的尝试来修复左右边缘,iPhone X模拟器中的结果如下:
波泰特:
风景:
请注意,不需要额外的努力,单元格和节标题会获得所需的插入,但标题视图不会。
我希望标题视图的左边缘与节标题的左边缘和单元格对齐。
我希望标题视图的右边缘停止在与段索引的左边缘相交的位置。请注意,肖像图片似乎已经这样做但如果你仔细观察,你可以告诉标题视图一直到表格视图的右边缘。你无法看到省略号的第三个.
,你几乎看不到章节标题视图后面的绿色。
我做过的一个尝试是将以下内容添加到我的表视图控制器中:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let header = tableView.tableHeaderView {
var insets = header.layoutMargins
insets.left = tableView.layoutMargins.left
insets.right = tableView.layoutMargins.right
header.layoutMargins = insets
}
}
该代码无效。
我设置了哪些属性以确保标题视图的左右边缘根据需要缩进?是否存在应该应用的约束?
请注意我在代码中做了所有事情。因此,请不要发布任何需要故事板或xib文件的解决方案。欢迎使用Swift或Objective-C中的答案。
对于想要复制此内容的任何人,请创建一个新的单一视图项目。调整主故事板以使用UITableViewController而不是计划UIViewController并对ViewController
使用以下内容:
import UIKit
class ViewController: UITableViewController {
// MARK: - UITableViewController methods
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
cell.accessoryType = .disclosureIndicator
return cell
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section Header"
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
let coll = UILocalizedIndexedCollation.current()
return coll.sectionIndexTitles
}
override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return index
}
// MARK: - UIViewController methods
override func viewDidLoad() {
super.viewDidLoad()
tableView.sectionIndexMinimumDisplayRowCount = 1
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 30)
label.backgroundColor = .green
label.text = "This is a really long Table Header label to make sure it is working properly."
label.sizeToFit()
tableView.tableHeaderView = label
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let header = tableView.tableHeaderView {
var insets = header.layoutMargins
insets.left = tableView.layoutMargins.left
insets.right = tableView.layoutMargins.right
header.layoutMargins = insets
}
}
}
答案 0 :(得分:2)
对于没有部分索引的UITableViews:
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
])
对于带有节索引的UITableView:
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
label.trailingAnchor.constraint(equalTo: tableView.layoutMarginsGuide.trailingAnchor)
])
答案 1 :(得分:1)
在将其添加到tableview后,您需要为标签添加一些自动布局约束:
…
tableView.tableHeaderView = label
//Add this
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: (label.superview?.safeAreaLayoutGuide.leadingAnchor)!).isActive = true
label.trailingAnchor.constraint(equalTo: (label.superview?.safeAreaLayoutGuide.trailingAnchor)!).isActive = true
此外,如果您想查看标签中的所有文字,请使用label.numberOfLines = 0
。
您可以删除添加到viewDidLayoutSubviews
的代码。
为了好玩,我在操场上做了一些实验,发现使用layoutMarginsGuide
并没有将标题标签的后缘推得足够远(我认为它正好出现在iPhone X但可能不在所有设备上,或者游乐场的行为有点不同)。我确实发现,对于至少有一个单元已经存在的表视图,我可以使用aCell.contentView.bounds.width
,减去表格视图的宽度并将结果除以2,并且标题标签将非常好地放在旁边部分索引。结果我写了一个辅助函数来设置约束。表视图是可选的,因此该函数可以与任何具有superview并且需要保持在安全区域内的视图一起使用。如果传入一个表视图,它可以有一个段索引,但它确实需要在第0行0区至少有一个单元格:
func constrain(view: UIView, inTableView aTableView: UITableView?) {
guard let container = view.superview else {
print("Constrain error! View must have a superview to be constrained!!")
return
}
view.translatesAutoresizingMaskIntoConstraints = false
view.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor).isActive = true
if let table = aTableView, let aCell = table.cellForRow(at: IndexPath(row: 0, section: 0)) {
let tableWidth = table.bounds.width
let cellWidth = aCell.contentView.bounds.width
view.trailingAnchor.constraint(equalTo: table.safeAreaLayoutGuide.trailingAnchor, constant: cellWidth - tableWidth).isActive = true
} else {
view.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor).isActive = true
}
}
我在使用它时确实发现了一个问题。当使用与文本设置为0行的标签时,它将覆盖第一部分标题和该部分的第一个单元格。它需要一些滚动才能将它们从标题下方取出。将标签剪切成一行虽然效果很好。