NSTableView первая строка изначально появляется за заголовком - PullRequest
0 голосов
/ 28 июня 2018

Я создаю tableView в моем приложении программно, и у меня есть эта проблема:

Всякий раз, когда размер содержимого моего tableView больше, чем его фрейм, первая строка tableView первоначально появляется под заголовком , но его можно легко прокрутить обратно в позицию.

Скриншоты того, как выглядит окно после начальной загрузки .

Размер содержимого больше фрейма tableView (проблема здесь):

enter image description here

Размер содержимого меньше, чем у tableView (все здесь хорошо):

enter image description here

Мой код класса NSViewController:

class MainViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

let label: NSTextField = {
    let label = NSTextField()
    label.stringValue = "Test App"
    label.font = NSFont.boldSystemFont(ofSize: 14)
    label.textColor = .white
    label.alignment = .center
    label.drawsBackground = false
    label.isBezeled = false
    label.isSelectable = true
    label.isEditable = false
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

let labelContainerView: NSView = {
    let view = NSView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

let tableView: NSTableView = {
    let tableView = NSTableView()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.usesAlternatingRowBackgroundColors = true

    let column = NSTableColumn(identifier: .init(rawValue: "MyColumnID"))
    column.headerCell.title = "Test"
    column.headerCell.alignment = .center
    tableView.addTableColumn(column)

    return tableView
}()

let scrollView: NSScrollView = {
    let scrollView = NSScrollView()
    scrollView.hasVerticalScroller = true
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    return scrollView
}()

override func loadView() {
    view = NSView()
    view.wantsLayer = true
}

var names: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()

    layoutUI()

    for i in 1...9 {
        let name = "Test \(i)"
        names.append(name)
    }

    scrollView.documentView = tableView

    tableView.delegate = self
    tableView.dataSource = self
}



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

    let newCell = MyCellView(identfier: NSUserInterfaceItemIdentifier(rawValue: "MyColumnID"))

    newCell.textView.stringValue = names[row]

    return newCell
}


func numberOfRows(in tableView: NSTableView) -> Int {
    return names.count
}

func layoutUI() {
    view.addSubview(labelContainerView)
    view.addSubview(scrollView)
    labelContainerView.addSubview(label)

    NSLayoutConstraint.activate([
        labelContainerView.topAnchor.constraint(equalTo: view.topAnchor),
        labelContainerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        labelContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        labelContainerView.heightAnchor.constraint(equalTo: view.heightAnchor,
                                                   multiplier: 1/5),

        label.centerXAnchor.constraint(equalTo: labelContainerView.centerXAnchor),
        label.centerYAnchor.constraint(equalTo: labelContainerView.centerYAnchor,
                                       constant: -4),

        scrollView.heightAnchor.constraint(equalTo: view.heightAnchor,
                                           multiplier: 4/5),
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
}

}

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

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

Когда NSTableView имеет NSTableHeaderView, NSScrollview фактически имеет ДВА NSClipview. Одна, доступная из свойства .contentView, содержит табличное представление, вторая содержит заголовок и NSVisualEffectView. Они оба являются подпредставлениями прокрутки.

Я заставил его вести себя, то есть показать верхнюю строку, настроив вставки contentView:

    scrollView.contentView.contentInsets = NSEdgeInsets(top: headerView!.frame.height, left: 0, bottom: 0, right: 0)

Я пробовал различные стратегии автоматического размещения, которые не работали или казались сомнительными.

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

Обзор (не код, а единственный способ получить его для форматирования):

    Scroll View Subviews: 4
    NSClipView
      NSTableBackgroundView (-250.0, -456.0, 1000.0, 456.0)
      NSTableView (0.0, 0.0, 500.0, 4750.0)
    NSClipView
      NSVisualEffectView (0.0, 0.0, 500.0, 23.0)
      NSTableHeaderView (0.0, 0.0, 500.0, 23.0)
    NSScroller
    NSScroller 

Два просмотра клипов с их рамками. 0 - просмотр содержимого:

    ClipView 0 (0.0, 0.0, 500.0, 438.0)
      NSTableBackgroundView 0 (-250.0, -456.0, 1000.0, 456.0)
      NSTableView 1 (0.0, 0.0, 500.0, 4750.0)
    ClipView 1 (0.0, 0.0, 500.0, 23.0)
      NSVisualEffectView 0 (0.0, 0.0, 500.0, 23.0)
      NSTableHeaderView 1 (0.0, 0.0, 500.0, 23.0)

Все еще не до конца понимаю, что происходит.

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

0 голосов
/ 29 июня 2018

Я бы не рекомендовал устанавливать NSTableView в коде. Это гораздо проще сделать в Интерфейсном Разработчике и может предотвратить нежелательные побочные эффекты. В любом случае, если NSTableView не отображает первую строку, как ожидалось, я бы использовал scrollToVisible в связанном NSScrollView, чтобы сделать первую строку видимой после загрузки данных.

...