Пользовательский NSScrollView не прокручивает NSTableHeaderView

#objective-c #cocoa #nstableview #nsscrollview

#objective-c #cocoa #nstableview #nsscrollview

Вопрос:

У меня есть NSTableView встроенный в пользовательский NSScrollView подкласс, в котором я иногда выполняю прокрутку программно, вот так:

 [[self contentView] scrollToPoint:newOffset];
[self reflectScrolledClipView:[self contentView]];
  

Когда я делаю это, NSTableView прокручивается нормально, но связанный с ним файл NSTableHeaderView не перемещается вместе с ним. Однако, если я использую мышь и прокручиваю NSScrollView нормально, они перемещаются вместе, как и должны.

Я полагаю, что, вероятно, где-то просто отсутствует одна строка, которая позволяет NSTableHeaderView знать, что она тоже должна прокручиваться, но я не знаю, что это такое. Кто-нибудь может помочь?

Комментарии:

1. Вы пробовали использовать -documentView вместо -contentView ?

2. @Bavarious Теперь у меня есть. Это не работает. 😛 Честно говоря, использование -documentView вместо -contentView в любом случае не имеет большого смысла; -documentView возвращает NSTableView , тогда как -contentView возвращает NSClipView . В этом случае я почти уверен, что мне нужен NSClipView .

Ответ №1:

Ну, я не знаю точно, какая черная магия происходит под капотом, когда вы прокручиваете NSScrollView содержащий NSTableHeaderView объект с помощью мыши, но, похоже, он обрабатывает это где-то внутри. Чтобы обойти это, я теперь только прокручиваю NSTableView программно (переопределяя функции, которые будут обрабатывать пользовательский ввод), а затем прокручиваю NSTableHeaderView сам, вот так:

 NSTableHeader *header = [[self documentView] headerView];
[header setBoundsOrigin:NSMakePoint(newOffset.x,[header bounds].origin.y)];
  

Комментарии:

1. Черная магия заключается в том, что NSScrollView проверяет представление документа на наличие метода / свойства «headerView» и, если найдено, обрабатывает его таким образом. Это нигде не задокументировано, что я могу найти, кроме этого списка рассылки: lists.apple.com/archives/cocoa-dev/2009/Jun/msg01464.html

Ответ №2:

Я столкнулся с той же проблемой в NSTableView на основе ячеек с Swift 5 / macOS 14.

NSScrollView, заключающий в себе NSTableView, владеет как contentView, так и headerView NSTableView (и cornerView, который я не использую), и обычно отвечает за координацию их прокрутки.

  • При прокрутке с помощью мыши внутренняя программа NSScrollView корректно обрабатывает прокрутку представления заголовка.
  • При программной прокрутке NSClipView с использованием scroll(to:) reflectScrolledClipView NSScrollView не удается прокрутить заголовок.

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

 extension NSTableView : ScrollingProtocol {

    func getScrollView() -> NSScrollView? {
        return enclosingScrollView
    }

    func getVisibleOrigin() -> NSPoint? {
        return enclosingScrollView?.documentVisibleRect.origin
    }

    func scrollToOrigin(_ targetOrigin: NSPoint) {
        guard let currentOrigin = getVisibleOrigin(),
            let scrollView = enclosingScrollView
            else { return }

        if (!NSEqualPoints(targetOrigin, currentOrigin)) {
            let clipView = scrollView.contentView
            clipView.scroll(to: targetOrigin)

            // Workaround because NSClipView.scroll(to:) does not scroll
            // the headerView of NSTableView
            if let headerView = headerView {
                let x = targetOrigin.x
                let y = headerView.bounds.origin.y
                if let headerClipView = headerView.superview as? NSClipView {
                    headerClipView.scroll(to: NSMakePoint(x, y))
                }
            }
            scrollView.reflectScrolledClipView(clipView)
        }
    }
}