代码之家  ›  专栏  ›  技术社区  ›  rmaddy

如何调整UITableView tableHeaderView的左右插入或边距?

  •  2
  • rmaddy  · 技术社区  · 7 年前

    tableViewHeader 对于表视图。该表还显示了右侧下方的截面索引。

    我创建了一个简单的测试应用程序,添加了几个虚拟行、一个节标题和节索引。

    下面是我使用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模拟器中的结果如下:

    Portait:

    enter image description here

    enter image description here

    我希望标题视图的左边缘与节标题和单元格的左边缘对齐。

    我希望标题视图的右边缘在它与节索引的左边缘相交的地方停止。请注意,肖像图片似乎已经这样做了,但如果仔细观察,可以看出标题视图一直到表视图的右边缘。你看不到第三个 .

    我曾尝试将以下内容添加到我的表视图控制器中:

    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
            }
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   joern    7 年前

    对于没有节索引的UITableViews:

    label.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
        label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
    ])
    

    对于具有截面索引的UITableViews:

    label.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
        label.trailingAnchor.constraint(equalTo: tableView.layoutMarginsGuide.trailingAnchor)
    ])
    
        2
  •  3
  •   theMikeSwan    7 年前

    将标签添加到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 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行的标签时,它会覆盖第一节标题和该节的第一个单元格。也需要一些滚动才能将它们从标题下取出。不过,将标签剪切到一行效果很好。