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)
}
}
}
精彩评论