开发者

Custom NSScrollView doesn't scroll NSTableHeaderView

I have an NSTableView embedded within a custom NSScrollView subclass, wherein I sometimes do scrolling programmatically, like so:

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

When I do this, the NSTableView scrolls fine, but its associated NSTableHeaderView doesn't move with it. If I use my mouse and scroll the NSScrollView normally, however, they move together like they should.

I figure I'm probably just missing a single line somewhere that lets the NSTableHeaderView know that it's supp开发者_如何转开发osed to scroll too, but I don't know what that is. Can anyone help?


Well, I don't know precisely what kind of black magic goes on under the hood when you scroll an NSScrollView containing an NSTableHeaderView with the mouse, but it looks like it handles it internally somewhere. To circumvent this, I now only scroll the NSTableView programatically (by overriding the functions that would handle user input), and then I scroll the NSTableHeaderView myself, like so:

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


I ran into the same issue on a cell-based NSTableView with Swift 5 / MacOS 14.

The NSScrollView enclosing an NSTableView owns both the contentView and the headerView of the NSTableView (and the cornerView, which I do not use), and is normally responsible of coordinating their scrolling.

  • When scrolling with mouse, the NSScrollView internal magic handle correctly the scrolling of the header view.
  • When scrolling programmatically the NSClipView using scroll(to:) + reflectScrolledClipView, NSScrollView fails to scroll of the headerView.

I use this protocol in order to scroll programmatically the headerView too, which allows me to scroll programmatically using this protocol:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜