私はかなり似たような問題を抱えていました。同期するスクロールビューが 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% の確率で機能し、たまにジッターが発生するだけです。横スクロール同期も問題なし。