6

ドキュメントSynchronizing Scroll Viewsを読み、ドキュメントとまったく同じようにしましたが、問題があります。

NSTableView と NSTextView を同期したい。最初にNSTableViewにNSTextViewを監視させ、TextViewをスクロールするとすべて問題ありませんが、TableViewをスクロールしようとすると、TableViewが最初に別の場所(おそらく数行後方)にジャンプし、その場所からスクロールし続けることがわかりました.

この問題は、TextView に TableView を監視させた後でも存在します。

誰が何が問題なのか知っていますか?TableView と TextView を同期できませんか?

編集: OK、TableView が最後のスクロール以降の場所に戻ることがわかりました。たとえば、TableView の一番上の行が 10 行目で、TextView をスクロールすると、TableView の一番上の行が 20 行目になり、TableView をもう一度スクロールすると、TableView は最初に 10 行目に戻ってからスクロールを開始します。

4

3 に答える 3

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];
}

次に、InterfaceBuilderでスクローラーを「表示」できるようにしました。ただし、非表示になっているため、画面に表示されず、ユーザーがクリックすることもできません。IB設定とプロパティが同等ではないことは驚くべきことですhiddenが、動作からはそうではないことは明らかです。

これは最善の解決策ではありませんが、私が思いついた最も簡単な回避策です(これまでのところ)。

于 2012-10-18T17:57:42.157 に答える
0

私はかなり似たような問題を抱えていました。同期するスクロールビューが 3 つあります。水平方向にのみスクロールするヘッダーです。縦にスクロールするだけのサイドバーです。ヘッダーの下、サイドバーの右側にあるコンテンツ領域です。ヘッダーとサイド バーは、コンテンツ領域と共に移動する必要があります。ヘッダーまたはサイドバーがスクロールされた場合、コンテンツ領域はヘッダーまたはサイドバーと一緒に移動する必要があります。

水平スクロールは決して問題ではありませんでした。垂直方向のスクロールにより、常に 2 つのビューが反対方向にスクロールされていました。

私がたどり着いた奇妙な解決策は、clipView サブクラスを作成することでした (箱から出してこない素晴らしいものが必要な場合は、ほとんど常に必要になるため、既に作成しています)。clipView サブクラスでは、プロパティを追加します。 BOOL isInverted であり、isFlipped のオーバーライドでは、self.isInverted を返します。

奇妙なことは、これらの反転の BOOL 値が設定され、最初から 3 つのビューすべてで一致することです。スクロール機械は確かにバグがあるようです。私が偶然見つけた回避策は、呼び出しの間にスクロール同期コードを挟み、サイドバーとコンテンツ ビューの両方を非反転に設定し、垂直スクロールを更新してから、両方を再び反転に設定することでした。逆スクロールをサポートしようとしているスクロール機構の古いコードである必要があります...

これらは、clipView の NSViewBoundsDidChangeNotification を観察するために NSNotificationCenter addObserver メソッドによって呼び出されるメソッドです。

- (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% の確率で機能し、たまにジッターが発生するだけです。横スクロール同期も問題なし。

于 2015-02-03T01:17:37.253 に答える