Как переопределить макет NSTableHeaderView?

Я пытаюсь создать собственный заголовок для моего NSTableView. Я хотел бы изменить шрифт заголовка текста и удалить границы и вертикальные разделители.

Мой текущий верхний и нижний заголовок показан ниже:

введите описание изображения здесь

Кто-нибудь знает, как мне это сделать, пожалуйста?

ОБНОВЛЕНИЕ: после применения исправления заголовок теперь выглядит так, как я и собирался:

введите описание изображения здесь

5 ответов

Решение

На самом деле оба ответа от mprudhom и Pronto внесли свой вклад в окончательное исправление. Большое спасибо вам обоим.

Я думал, что опубликую свой окончательный ответ, чтобы любой, кто следит за ним, мог видеть, как я это исправил.

Я не мог использовать один только код mprudhom, так как в моей таблице был только NSTableHeaderView и нет TableHeaderCells. К счастью, Пронто пришел на помощь по этому поводу:

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

Я использовал код NSTableHeaderCell непосредственно из mprudhom:

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)
    }
}

Один из способов сделать это в вашем NSTableViewDelegate'sviewForTableColumn -функции:

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
}

Приведенные выше ответы также работают напрямую, вы можете использовать в 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)])
              }
}

Вам нужно будет взять на себя рисунок путем подкласса 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 = DataTableHeaderCell(textCell: title)
col.title = title
self.dataTableView.addTableColumn(col)

В противном случае вы можете просто установить имя вашего класса на имя вашего подкласса в Интерфейсном Разработчике.

Что вроде работает в macOS 11:

  1. Установить фон NSTableHeaderCell

             func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
     tableColumn?.headerCell.drawsBackground = true
     tableColumn?.headerCell.backgroundColor = .orange
     ...
    
  2. Установите стиль NSTableView в IB на полную ширину

Другие вопросы по тегам