Какой правильный способ поместить некоторый текст по вертикали по центру в строку NSTableView?

У моего приложения OS X есть NSTableView с большей высотой строки:

myTableView.rowSizeStyle = .large

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

См. код ниже. У меня три столбца, а первые два используют NSTextField и NSTextView для ввода некоторого текста. Третий - это кнопка флажка.

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    if (tableColumn?.identifier == "Column1") {

        let field = NSTextField()
        field.stringValue = "someText"
        field.isBordered = false
        field.isEditable = false
        field.backgroundColor = NSColor.red
        return field
    } else if (tableColumn?.identifier == "Column2") {

        let field = NSTextView()
        field.string = "someText"
        field.backgroundColor = NSColor.green
        return field
    } else if (tableColumn?.identifier == "Column3") {

        let field = NSButton()
        field.setButtonType(NSSwitchButton)
        field.title = "check me"
        return field
    }

    return nil
}

Мой код в значительной степени основан на документе Apple: "Создание и настройка ячейки NSTextField".

Вот результат:

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

Как вы можете видеть, тексты в первых двух столбцах не вертикально центрированы, а флажок автоматически центрируется по вертикали.

При использовании func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? точно так же, как показал документ Apple, какой правильный способ разместить текст так, чтобы он мог быть вертикально центрирован?

EDIT: По какой-то причине я не использую Interface Builder. Поэтому возникает вопрос о программном программировании пользовательского интерфейса.

Ответ 1

Простое решение:

Не создавайте элементы интерфейса в коде, сделайте это в интерфейсе Builder. Связанный документ Apple гласит:

Наиболее вероятная ситуация заключается в том, что вы разработали ячейку в Interface Builder и захотите ее извлечь, а затем заполните значения в этой ячейке

  • Для столбца NSTextView удалить предопределенный вид ячейки таблицы и перетащить экземпляр NSTextView в столбец. Измените размер представления и добавьте отсутствующие ограничения AutoLayout.
  • Для второго столбца с вертикальной ориентацией используйте предопределенный вид ячейки таблицы и добавьте ограничения Align Center X и Align Center Y к объекту NSTextField.
  • Для столбца флажка удалите экземпляр NSTextField в предопределенном представлении ячейки таблицы, перетащите флажок в представление и добавьте также Align Center Y и другие отсутствующие ограничения.

Настоятельно рекомендуется использовать Cocoa Bindings для подключения представления таблицы к источнику данных.

Этот снимок экрана ниже не содержит кода, кроме метода

func numberOfRows(in tableView: NSTableView) -> Int {
    return 10
}

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

Edit:

В качестве альтернативы для Column1 - столбец NSTextField - оберните текстовое поле в экземпляр NSTableCellView и укажите фрейм, например (оператор switch работает быстрее, а tableColumn может быть только nil если в представлении таблицы также используются секции/группы строк):

   switch tableColumn!.identifier {

    case "Column1":
        let cellView = NSTableCellView()
        // the value for y: in the frame should be row.height / 2 - textField.height / 2
        let field = NSTextField(frame: NSRect(x:0.0, y:10.0, width:tableColumn!.width, height:17.0))
        field.stringValue = "someText"
        field.isBordered = false
        field.isEditable = false
        field.backgroundColor = NSColor.red
        cellView.addSubview(field)
        return cellView

    case "Column2":

        ...

    default: return nil

    }

Примечание:

Обратите внимание, что текст в столбце NSTextView может быть только в центре внутри текстового представления через NSAttributedString или вам нужно указать кадр для охватывающего вида прокрутки.

PS: Это так намного проще в Interface Builder - SCNR.

Ответ 2

поскольку просмотр ячеек в формате @vadian - это ничего, кроме NSTableCellView, вам просто нужно настроить рамку как фрейм: NSRect (x: 0.0, y: myTableView.rowHeight/2, width: tableColumn!.width, height: myTableView.rowHeight

let cellView = NSTableCellView()
        let field = NSTextField(frame: NSRect(x:0.0, y:myTableView.rowHeight/2, width:tableColumn!.width, height:myTableView.rowHeight))
        field.stringValue = "someText"
        field.isBordered = false
        field.isEditable = false
        field.backgroundColor = NSColor.red
        cellView.addSubview(field)
        return cellView

Ответ 3

Прежде всего, не создавайте объекты прагматически, и если вы хотите сделать класс, унаследованный от TabelviewCell и весь ваш код ячейки, здесь. После этого вы должны проверить ограничения для ячейки и feilds, которые вы пытаетесь управлять.

Он будет работать нормально, если вы просто добавите поля в stroyboard и установите ограничения на них. попробуйте ярлык и сделайте его многострочным после фиксации его горизонтальной ширины.