【问题标题】:How do I override layout of NSTableHeaderView?如何覆盖 NSTableHeaderView 的布局?
【发布时间】:2015-12-16 11:24:22
【问题描述】:

我正在尝试为我的 NSTableView 生成一个自定义标题。我想更改标题文本的字体并删除边框和垂直分隔符。

我当前的顶部和底部标题如下所示:

请问有人知道我该怎么做吗?

更新:应用修复后,标题现在看起来像我想要的那样:

【问题讨论】:

    标签: swift nstableheaderview


    【解决方案1】:

    什么似乎在 macOS 11 中起作用:

    1. 设置 NSTableHeaderCell 背景

       func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
       tableColumn?.headerCell.drawsBackground = true
       tableColumn?.headerCell.backgroundColor = .orange
       ...
      
    2. 将 IB 中的 NSTableView 样式设置为全宽

    【讨论】:

      【解决方案2】:

      以上答案也可以直接在 viewDidLoad 中使用

      override func viewDidLoad() {
              super.viewDidLoad()   
              tableView.tableColumns.forEach { (column) in
                      column.headerCell.backgroundColor = NSColor.white
                      column.headerCell.drawsBackground = true
                      column.headerCell.isBordered = false
                      column.headerCell.attributedStringValue = NSAttributedString(string: column.title, attributes: [NSAttributedString.Key.font: NSFont.systemFont(ofSize: 13)])
                    }
      }
      

      【讨论】:

        【解决方案3】:

        您需要通过子类化NSTableHeaderCell 自己接管绘图,如下所示:

        final class CustomTableHeaderCell : NSTableHeaderCell {
            required init?(coder aDecoder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }
        
            override init(textCell: String) {
                super.init(textCell: textCell)
                self.font = NSFont.boldSystemFontOfSize(20)
            }
        
            override func drawWithFrame(cellFrame: NSRect, inView controlView: NSView) {
                // skip super.drawWithFrame(), since that is what draws borders
                self.drawInteriorWithFrame(cellFrame, inView: controlView)
            }
        
            override func drawInteriorWithFrame(cellFrame: NSRect, inView controlView: NSView) {
                let titleRect = self.titleRectForBounds(cellFrame)
                self.attributedStringValue.drawInRect(titleRect)
            }
        }
        

        如果您以编程方式设置表格,您会这样做:

        let col = NSTableColumn(identifier: id)
        col.headerCell = CustomTableHeaderCell(textCell: title)
        col.title = title
        self.dataTableView.addTableColumn(col)
        

        否则,您应该可以在 Interface Builder 中将类的名称设置为子类的名称。

        【讨论】:

        • 谢谢。我想我只是少了一步。我的表只有一个 NSTableHeaderView,我无法选择 TableHeaderCell 来对其进行子类化。
        【解决方案4】:

        实际上,来自 mprudhom 和 Pronto 的答案都对最终修复做出了很好的贡献。非常感谢你们。

        我想我会发布我的最终答案,以便任何关注的人都可以看到我是如何修复它的。

        我不能单独使用 mprudhom 的代码,因为我的表只有一个 NSTableHeaderView 而没有 TableHeaderCells。幸运的是,Pronto 解决了这个问题:

        class MyTable: NSTableView, NSTableViewDataSource, NSTableViewDelegate
        {
            override func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView?
            {
                tableColumn!.headerCell = MyTableHeaderCell(textCell: tableColumn!.identifier)
            }
        }
        

        我直接从 mprudhom 使用了 NSTableHeaderCell 代码:

        final class MyTableHeaderCell : NSTableHeaderCell
        {
            required init?(coder aDecoder: NSCoder)
            {
                fatalError("init(coder:) has not been implemented")
            }
        
            override init(textCell: String)
            {
                super.init(textCell: textCell)
                self.font = NSFont.boldSystemFontOfSize(14)
            }
        
            override func drawWithFrame(cellFrame: NSRect, inView controlView: NSView)
            {
                //super.drawWithFrame(cellFrame, inView: controlView)//, since that is what draws borders
                self.drawInteriorWithFrame(cellFrame, inView: controlView)
            }
        
            override func drawInteriorWithFrame(cellFrame: NSRect, inView controlView: NSView)
            {
                let titleRect = self.titleRectForBounds(cellFrame)
                self.attributedStringValue.drawInRect(titleRect)
            }
        }
        

        一旦实现了这两种方法,我遇到了最后一个问题,即 NSTableHeaderView 按要求绘制时没有边框,但背景却是灰色的。所以我用这个方法覆盖了 NSTableHeaderView 类:

        class ForecastHeaderView : NSTableHeaderView
        {
            required init?(coder: NSCoder)
            {
                super.init(coder: coder)
            }
        
            override init(frame frameRect: NSRect) 
            {
                super.init(frame: frameRect)
                self.wantsLayer = true
            }
        
            override func drawLayer(layer: CALayer, inContext ctx: CGContext)
            {
                super.drawLayer(layer, inContext: ctx)
                layer.backgroundColor = CGColorCreateGenericGray(1.0, 1.0)
            }
        }
        

        【讨论】:

        • 你在哪里使用自定义NSTableHeaderView (ForecastHeaderView)。或者你在哪里实现它以便 TableView 使用这个自定义类。
        • 当您通过 InterfaceBuilder 查看表格视图时,您会看到一个 Scroll View 对象、一个 Clip VIew 对象、实际的 Table View 和其中的列。与表视图处于同一级别的是 NSTableViewHeader 对象。选择它并将自定义类型更改为“ForecastHeaderView”,或者您的自定义标题视图类型。
        • 我想知道您是否对 Swift 3 的此代码有任何更新。我已经尝试了您的代码,一些 API 已更改,但无法编译。我试图弄清楚,但由于图层的处理方式不同。我无法覆盖drawLayer。我试图通过扩展 CALayer 来找到解决方法,但仍然无法实现。
        • 我和@Amir 有同样的问题。我正在使用 Swift 5,这在 macOS 11 上似乎是不可能实现的。
        【解决方案5】:

        一种方法,在你的NSTableViewDelegate'sviewForTableColumn -function:

        if tableColumn!.identifier == "description" {
            let cell = NSTableHeaderCell()
            cell.title = "New Title"
            cell.backgroundColor = NSColor.redColor()
            cell.drawsBackground = true
            cell.bordered = false
            cell.font = NSFont(name: "Helvetica", size: 16)
            tableColumn!.headerCell = cell
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-28
          相关资源
          最近更新 更多