【问题标题】:Changing UITableView section header without tableView:titleForHeaderInSection在没有 tableView:titleForHeaderInSection 的情况下更改 UITableView 部分标题
【发布时间】:2010-12-07 20:52:30
【问题描述】:

我正在尝试在选择来自该部分的单元格UITableView中的部分中的标题标题。 tableView:titleForHeaderInSection 由应用程序触发,因此无济于事。我可以打电话给reloadData,但性能会受到影响,因为应用程序必须重新加载所有可见单元格。我也尝试使用自定义标头,但这也会导致一些性能问题。

有没有办法获得默认标题视图使用的UILabel 的句柄并手动更改其文本?

【问题讨论】:

    标签: ios uitableview


    【解决方案1】:

    似乎没有任何标准 API 可用于访问系统提供的节标题视图。您是否尝试过更有针对性的reloadSections:withRowAnimation 让 UIKit 显示新的标题文本?

    您在使用自定义部分标题视图时发现了哪些性能问题?我怀疑标准的不仅仅是UILabel

    【讨论】:

    • 似乎我可能不得不使用 reloadSections,即使它几乎与重新加载整个表一样慢(至少对于我的应用程序而言)。我每次都被 Cocoa API 挫败。我尝试使用循环队列来重用一组 UILabel 并在 viewForHeader 中返回它们,但是 viewForHeader 被调用了很多单元格(甚至是不可见的单元格!),我需要为每个单元格创建一个单独的 UILabel,这简直太糟糕了。啊!
    【解决方案2】:

    这是一个 WAG,我可以想出很多为什么它可能不起作用的原因,但是您不能遍历子视图并找到您正在寻找的那个吗?例如

    for (UIView *v in self.tableView.subviews) {
        // ... is this the one?
    }
    

    【讨论】:

      【解决方案3】:

      由于 UITableView 不会将节头视图入队和出队以供重用,因此您不妨看看将所有节头视图存储在内存中是否可行。请注意,您必须使用背景等创建自己的节标题视图,但它可以让您更加灵活和功能。

      您也可以尝试标记节标题视图(还需要您创建自己的节标题视图)并根据需要从 tableview 中获取它们。

      【讨论】:

        【解决方案4】:

        调用 [tableView endUpdates] 可能会提供所需的结果,而不会对性能造成太大影响。

        [self.tableView beginUpdates];
        [self.tableView endUpdates];
        
        // forces the tableView to ask its delegate/datasource the following:
        //   numberOfSectionsInTableView:
        //   tableView:titleForHeaderInSection:
        //   tableView:titleForFooterInSection:
        //   tableView:viewForHeaderInSection:
        //   tableView:viewForFooterInSection:
        //   tableView:heightForHeaderInSection:
        //   tableView:heightForFooterInSection:
        //   tableView:numberOfRowsInSection:
        

        【讨论】:

        • 在 iOS10/11 (swift) 我注意到 tableView:viewForHeaderInSection:tableView:viewForFooterInSection: 没有被调用所以你需要自己改变视图
        【解决方案5】:

        与:

        [self.tableView headerViewForSection:i]
        

        您可以获取第 i 部分的视图,然后手动“更新”它

        如果您的视图只是自动生成的标签,这甚至可以工作,但您必须自己调整它的大小。 所以如果你尝试:

        [self.tableView headerViewForSection:i].textLabel.text = [self tableView:self.tableView titleForHeaderInSection:i];
        

        您将设置文本,但您不会设置标签大小。您可以从 NSString 获取所需的大小来自己设置:

        [label.text sizeWithFont:label.font];
        

        【讨论】:

        • Hackish 并且不建议这样做,但这正是原始问题所要求的。所以+1。
        • [self.tableView headerViewForSection:i] 总是给出 nil 值
        • 如果 headerViewForSection 返回 nil 这意味着标题视图不可见。适用于动态表。
        • 我找到的唯一可行的解​​决方案。 sizeWithFont 已弃用。或者,您可以将标签的框架宽度设置为其父视图宽度
        【解决方案6】:

        其中一个解决方案是管理包含标签引用的多个节标题的外部数组并在外部更新它们。

        【讨论】:

          【解决方案7】:

          您可以直接设置节标题标签的标题。例如,设置第零节的标题:

          UITableViewHeaderFooterView *sectionZeroHeader = [self.tableView headerViewForSection:0];
          NSString *sectionZeroLabel = @"Section Zero";
          [sectionZeroHeader.textLabel setText:[sectionZeroLabel uppercaseString]];
          [sectionZeroHeader setNeedsLayout];
          

          一定要告诉节标题视图它需要布局,否则新文本可能会被截断。此外,部分标签通常都是大写的。

          【讨论】:

          • 如果您使用自动高度,这似乎不起作用。
          【解决方案8】:

          为了完整起见,我们都在寻找的方法是这个私有 API,它的名称完全符合您的期望:

          -(void)_reloadSectionHeaderFooters:withRowAnimation:
          

          例如:

          [tableView _reloadSectionHeaderFooters:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic]
          

          不过,我不建议使用它。

          【讨论】:

            【解决方案9】:

            如果您只想更新一个部分,最好的方法是tableView.headerView。如果 header 不可见,则返回 nil,因此不会加载额外的 headers。

            if let header = tableView.headerView(forSection: i) {
                header.textLabel!.text = "new title"
                header.setNeedLayout()
            }
            

            如果要更新所有可见的节标题,最好在显示视图之前将标题标记设置为节,并在需要时枚举子视图:

            func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
                view.tag = section
                // additional customization
            }
            
            func udpateVisibleSectionHeaders() {
                for subview in tableView.subviews {
                    if let header = subview as? UITableViewHeaderFooterView {
                        let section = header.tag
                        header.textLabel!.text = "new title"
                        header.setNeedsLayout()
                    }
                }
            }
            

            别忘了打电话给setNeedsLayout,否则标签会被截断。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-10-23
              • 1970-01-01
              • 2011-03-18
              • 1970-01-01
              • 1970-01-01
              • 2021-06-13
              • 2013-02-27
              相关资源
              最近更新 更多