NSTableView 中的 NSTextView 阻止滚动
NSTextView inside NSTableView Blocks Scrolling
我有一个 NSTableView
,并且在每个 table 行中有一个 NSTextView
。我在故事板的 NSTextView
上禁用了滚动。我可以很好地滚动我的 NSTableView
,但是当我的鼠标光标位于 NSTextView
的顶部时,滚动停止。我认为这是因为 NSTextView
正在拦截滚动行为。
箭头指向 NSTextView
:
请记住 NSTextView
属于子类 NSTableViewCell
。
class AnnouncementsVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
@IBOutlet weak var tableView: NSTableView!
override func viewDidLoad() {
//...
}
func numberOfRows(in tableView: NSTableView) -> Int {
//...
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
//...
}
}
class AnnouncementTableCell: NSTableCellView{
@IBOutlet weak var message: NSTextView!
}
如何让 NSTextView
将其滚动事件向上传递给其父 NSTableView
?我的猜测是我需要 scrollWheel(with event: NSEvent)
但我不确定它的去向,因为我在这里有两个不同的 类。
实现此目的的一种方法是继承 NSScrollView
并实现 scrollWheel:
以有条件地 (1) 根据需要在子类实例中使用滚动事件,或 (2) 转发它们到封闭的滚动视图,基于您实例的当前滚动位置。
这是我过去使用过的一个相当基本的实现 (Obj-C):
- (void)scrollWheel:(NSEvent *)e {
if(self.enclosingScrollView) {
NSSize
contSize = self.contentSize,
docSize = [self.documentView bounds].size,
scrollSize = NSMakeSize(MAX(docSize.width - contSize.width, 0.0f),
MAX(docSize.height - contSize.height,0.0f) );
NSPoint
scrollPos = self.documentVisibleRect.origin,
normPos = NSMakePoint(scrollSize.width ? scrollPos.x/scrollSize.width : 0.0,
scrollSize.height ? scrollPos.y/scrollSize.height : 0.0 );
if( ((NSView*)self.documentView).isFlipped ) normPos.y = 1.0 - normPos.y;
if( ( e.scrollingDeltaX>0.0f && normPos.x>0.0f)
|| ( e.scrollingDeltaX<0.0f && normPos.x<1.0f)
|| ( e.scrollingDeltaY<0.0f && normPos.y>0.0f)
|| ( e.scrollingDeltaY>0.0f && normPos.y<1.0f) ) {
[super scrollWheel:e];
}
else
[self.nextResponder scrollWheel:e];
}
else
// Don't bother when not nested inside another NSScrollView
[super scrollWheel:e];
}
它还有很多不足之处,比如独立处理 deltaX 和 deltaY 组件,但也许它对您的情况来说已经足够了。
这是一个运行良好的 Swift (4.2) 版本:
class MyScrollClass: NSScrollView{
override func scrollWheel(with event: NSEvent) {
self.nextResponder?.scrollWheel(with: event)
}
}
只需添加子 class 您的 NSScrollView
即可。
我有一个 NSTableView
,并且在每个 table 行中有一个 NSTextView
。我在故事板的 NSTextView
上禁用了滚动。我可以很好地滚动我的 NSTableView
,但是当我的鼠标光标位于 NSTextView
的顶部时,滚动停止。我认为这是因为 NSTextView
正在拦截滚动行为。
箭头指向 NSTextView
:
请记住 NSTextView
属于子类 NSTableViewCell
。
class AnnouncementsVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
@IBOutlet weak var tableView: NSTableView!
override func viewDidLoad() {
//...
}
func numberOfRows(in tableView: NSTableView) -> Int {
//...
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
//...
}
}
class AnnouncementTableCell: NSTableCellView{
@IBOutlet weak var message: NSTextView!
}
如何让 NSTextView
将其滚动事件向上传递给其父 NSTableView
?我的猜测是我需要 scrollWheel(with event: NSEvent)
但我不确定它的去向,因为我在这里有两个不同的 类。
实现此目的的一种方法是继承 NSScrollView
并实现 scrollWheel:
以有条件地 (1) 根据需要在子类实例中使用滚动事件,或 (2) 转发它们到封闭的滚动视图,基于您实例的当前滚动位置。
这是我过去使用过的一个相当基本的实现 (Obj-C):
- (void)scrollWheel:(NSEvent *)e {
if(self.enclosingScrollView) {
NSSize
contSize = self.contentSize,
docSize = [self.documentView bounds].size,
scrollSize = NSMakeSize(MAX(docSize.width - contSize.width, 0.0f),
MAX(docSize.height - contSize.height,0.0f) );
NSPoint
scrollPos = self.documentVisibleRect.origin,
normPos = NSMakePoint(scrollSize.width ? scrollPos.x/scrollSize.width : 0.0,
scrollSize.height ? scrollPos.y/scrollSize.height : 0.0 );
if( ((NSView*)self.documentView).isFlipped ) normPos.y = 1.0 - normPos.y;
if( ( e.scrollingDeltaX>0.0f && normPos.x>0.0f)
|| ( e.scrollingDeltaX<0.0f && normPos.x<1.0f)
|| ( e.scrollingDeltaY<0.0f && normPos.y>0.0f)
|| ( e.scrollingDeltaY>0.0f && normPos.y<1.0f) ) {
[super scrollWheel:e];
}
else
[self.nextResponder scrollWheel:e];
}
else
// Don't bother when not nested inside another NSScrollView
[super scrollWheel:e];
}
它还有很多不足之处,比如独立处理 deltaX 和 deltaY 组件,但也许它对您的情况来说已经足够了。
这是一个运行良好的 Swift (4.2) 版本:
class MyScrollClass: NSScrollView{
override func scrollWheel(with event: NSEvent) {
self.nextResponder?.scrollWheel(with: event)
}
}
只需添加子 class 您的 NSScrollView
即可。