11

I have an NSScrollView containing an NSImageView, which resizes based on various factors. When it resizes I have generally changed the image, so I scroll the NSScrollView to the top. This works fine. However, when I start to scroll the NSScrollView again, it moves a few pixels and then (most of the time) jumps to the bottom of the scroll. After it jumps once, it works as normal until I move the scroller to the top again. This is driving me insane. All I'm really doing is this:

[_imageView setImage: anNSImage];

NSRect frame;

NSSize imageSize = [anNSImage] size];
frame.size = imageSize;
frame.origin = NSZeroPoint;

[_imageView setFrame: frame];
[[_mainScrollview contentView] scrollToPoint: NSMakePoint(0, [_imageView frame].size.height - [_mainScrollview frame].size.height)];
Nick Locking
  • 2,147
  • 2
  • 26
  • 42
  • I comment in the hope that this question will be noticed by someone, because I am getting quite desperate. My NSScrollView is now flipped, which works better, because I can just avoid doing scrollToPoint altogether. In this case, the scroll point remains static when I change the content, so if it's at the top when I switch, there it stays. – Nick Locking Jan 05 '11 at 19:25
  • However, I still want to set it initially. I set it once, it changes position, I start to scroll, it jumps to the bottom. I've tried setting reflectScrolledClipView, to no avail. – Nick Locking Jan 05 '11 at 19:26
  • I have a problem almost the same as yours, anyone can help? http://stackoverflow.com/questions/6596567/synchronize-two-nsscrollview – disorderdev Jul 07 '11 at 14:19
  • I'm hitting the same issue. Is this a bug in NSScrollView? Because I can't seem to find a single answer online, and this question has been asked multiple times. Is there even a workaround? – Chetan Jul 26 '11 at 00:22
  • Also, let me guess. Did you hide the vertical scroller on the scroll view? Because I think that's what triggers this (potential) bug. – Chetan Jul 26 '11 at 00:33

6 Answers6

11

Nick, thanks for your code. I modified your code and it works well now. First, you need to scroll the vertical scroller to top. Second, scroll the content view.

    // Scroll the vertical scroller to top
    if ([_scrollView hasVerticalScroller]) {
        _scrollView.verticalScroller.floatValue = 0;
    }

    // Scroll the contentView to top
    [_scrollView.contentView scrollToPoint:NSMakePoint(0, ((NSView*)_scrollView.documentView).frame.size.height - _scrollView.contentSize.height)];
Vince Yuan
  • 10,533
  • 3
  • 32
  • 27
  • Thanks! gah this is the thing that finally worked... now I need to understand why scrollToPoint: works all the time, but scrollPoint: and scrollRectToVisible: sometimes are problematic. – Keith Knauber Nov 20 '15 at 00:52
3

To circumvent this bug you simply need to enable the scrollers and then set the hidden property of the scrollers. As NSScrollers inherit from NSView this just stops them from displaying themselves:

mainScrollView.hasHorizontalScroller = YES;
mainScrollView.hasVerticalScroller = YES;
mainScrollView.verticalScroller.hidden = YES;
mainScrollView.horizontalScroller.hidden = YES;

Works for me at least. Only tested on OS 10.7.2 though.

Does anyone have a radar filed on this one btw? They won't fix it if nobody tells them. :)

felinira
  • 1,644
  • 15
  • 21
  • 1
    This works, but you have to be careful when you set the `hidden` property. Apparently, `windowDidLoad` is too early, for example. – jmk Oct 18 '12 at 18:03
2

Seems I can use reflectScrolledClipView: instead of set scrollers' values to sync the position. Ex.

[self.scrollView.contentView scrollToPoint:NSMakePoint(300, 0)];
[self.scrollView reflectScrolledClipView:self.scrollView.contentView]; // synced then
lk_vc
  • 1,136
  • 20
  • 26
2

on macOS Sierra, [_scrollView.contentView scrollToPoint:]; was buggy and was causing erratic flickering. However using [_scrollView.documentView scrollPoint:] cleared up all of those issues for me. This is also the suggested method by Apple in their tutorial found here.

Charlton Provatas
  • 2,184
  • 25
  • 18
  • https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/NSScrollViewGuide/Articles/Scrolling.html – GoKu Jun 13 '19 at 06:44
1

My hacky solution. Turn on Show Vertical Scroller (like Chetan said, this is what triggers the bug). Send table view to back. Expand left edge of table view until the scroller is covered by whatever's to the right edge of it.

overcyn
  • 103
  • 1
  • 6
-4

You set the scrollView.contentOffset = CGPointMake(0,0). Or according to your requirement. Set contectoffset after you change the image.

Raxit
  • 824
  • 7
  • 12