2011-07-06 83 views
4

我阅读文档Synchronizing Scroll Views,并做了完全一样的文件,但有一个isssue。同步两个NSScrollView

我想同步一个NSTableView和一个NSTextView。首先让NSTableView监视NSTextView,并且当我滚动TextView时一切正常,但是当我尝试滚动TableView时,我发现TableView将首先跳转到另一个地方(可能是向后几行),然后继续从该位置滚动。

即使我让TextView监视TableView,这个问题仍然存在。

有人知道有什么问题吗?我不能同步TableView和TextView吗?

编辑: 好吧,现在我发现TableView将回到自上次滚动以来的位置。例如,TableView的第一行是第十行,然后我滚动TextView,现在TableView的最上一行是第20行,如果我再次滚动TableView,TableView将首先返回第10行,然后开始滚动。

回答

3

我在解决非常类似的情况时遇到了这个确切的问题(在Lion上)。我注意到这只发生在滚动条被隐藏时 - 但我确认它们仍然存在于笔尖中,并且仍然正确地实例化。

我甚至确保打电话给-[NSScrollView reflectScrolledClipView:],但它没有什么区别。看起来好像这是NSScrollView中的一个错误。

无论如何,我能够通过创建一个自定义滚动类来解决这个问题。我所要做的只是重写以下类方法:

+ (BOOL)isCompatibleWithOverlayScrollers 
{ 
    // Let this scroller sit on top of the content view, rather than next to it. 
    return YES; 
} 

- (void)setHidden:(BOOL)flag 
{ 
    // Ugly hack: make sure we are always hidden. 
    [super setHidden:YES]; 
} 

然后,我允许滚动条在界面构建器中“可见”。但是,由于它们隐藏起来,它们不会出现在屏幕上,并且它们不能被用户点击。令人惊讶的是,IB设置和hidden属性并不相同,但从行为上看,它们看起来并不清楚。

这不是最好的解决方案,但它是我想出的最简单的解决方法(到目前为止)。

+0

伟大的解决方案! – mohacs

+0

谢谢你,我遇到了一个类似的问题,我试图隐藏叠加滚动条,但它会打破滚动视图中的双指手势滚动。使用这个方法而不是'[scrollView setHasVerticalScroller:NO]'实现了希望隐藏滚动条的结果,但让scrollView仍然正确滚动。 – Andrew

0

我有一个相当类似的问题。 我有3个滚动视图进行同步。 一个只是水平滚动的标题。 一个是只能垂直滚动的侧栏。 其中一个是标题下方的内容区域,并位于侧边栏的右侧。 标题和边栏应随内容区域一起移动。 如果滚动,内容区域应该随标题或侧栏一起移动。

水平滚动从来都不是问题。 垂直滚动总是导致两个视图滚动到相反的方向。

奇怪的解决方案我来创建一个clipView子类(我已经做了,因为你几乎总是需要如果你想要什么好东西,不会出来的盒子。) 在clipView子类,我添加一个属性BOOL isInverted并在重载isFlipped我返回self.isInverted。

奇怪的是,这些用于翻转的BOOL值是从一开始就在所有3个视图中设置和匹配的。 看来,滚动机械确实是越野车。 我偶然发现的解决方法是在调用之间夹入滚动同步代码以将侧栏和内容视图设置为未翻转,然后更新任何垂直滚动,然后再次设置翻转。 必须在滚动机械试图支持倒滚动一些老代码...

这些是由NSNotificationCenter的addObserver方法称为观察NSViewBoundsDidChangeNotification为clipViews方法。

- (void)synchWithVerticalControlClipView:(NSNotification *)aNotification 
{ 
    NSPoint mouseInWindow = self.view.window.currentEvent.locationInWindow; 
    NSPoint converted = [self.verticalControl.enclosingScrollView convertPoint:mouseInWindow fromView:nil]; 

    if (!NSPointInRect(converted, self.verticalControl.enclosingScrollView.bounds)) { 
     return; 
    } 

    [self.contentGridClipView setIsInverted:NO]; 
    [self.verticalControlClipView setIsInverted:NO]; 

     // ONLY update the contentGrid view. 
    NSLog(@"%@", NSStringFromSelector(_cmd)); 
    NSPoint changedBoundsOrigin = self.verticalControlClipView.documentVisibleRect.origin; 

    NSPoint currentOffset = self.contentGridClipView.bounds.origin; 
    NSPoint newOffset = currentOffset; 

    newOffset.y = changedBoundsOrigin.y; 

    NSLog(@"\n changedBoundsOrigin=%@\n currentOffset=%@\n newOffset=%@", NSStringFromPoint(changedBoundsOrigin), NSStringFromPoint(currentOffset), NSStringFromPoint(newOffset)); 

    [self.contentGridClipView scrollToPoint:newOffset]; 
    [self.contentGridClipView.enclosingScrollView reflectScrolledClipView:self.contentGridClipView]; 

    [self.contentGridClipView setIsInverted:YES]; 
    [self.verticalControlClipView setIsInverted:YES]; 
} 

- (void)synchWithContentGridClipView:(NSNotification *)aNotification 
{ 
    NSPoint mouseInWindow = self.view.window.currentEvent.locationInWindow; 
    NSPoint converted = [self.contentGridView.enclosingScrollView convertPoint:mouseInWindow fromView:nil]; 

    if (!NSPointInRect(converted, self.contentGridView.enclosingScrollView.bounds)) { 
     return; 
    } 

    [self.contentGridClipView setIsInverted:NO]; 
    [self.verticalControlClipView setIsInverted:NO]; 

     // Update BOTH the control views. 
    NSLog(@"%@", NSStringFromSelector(_cmd)); 
    NSPoint changedBoundsOrigin = self.contentGridClipView.documentVisibleRect.origin; 

    NSPoint currentHOffset = self.horizontalControlClipView.documentVisibleRect.origin; 
    NSPoint currentVOffset = self.verticalControlClipView.documentVisibleRect.origin; 

    NSPoint newHOffset, newVOffset; 
    newHOffset = currentHOffset; 
    newVOffset = currentVOffset; 

    newHOffset.x = changedBoundsOrigin.x; 
    newVOffset.y = changedBoundsOrigin.y; 

    [self.horizontalControlClipView scrollToPoint:newHOffset]; 
    [self.verticalControlClipView scrollToPoint:newVOffset]; 

    [self.horizontalControlClipView.enclosingScrollView reflectScrolledClipView:self.horizontalControlClipView]; 
    [self.verticalControlClipView.enclosingScrollView reflectScrolledClipView:self.verticalControlClipView]; 

    [self.contentGridClipView setIsInverted:YES]; 
    [self.verticalControlClipView setIsInverted:YES]; 
} 

这工作99%的时间,只有偶尔的抖动。 水平滚动同步没有问题。