NSScrollView scroll bars are of the wrong length

2019-07-06 17:01发布

I have a Cocoa window, whose content view contains an NSScrollView that, in turns, contains a fixed-size NSView.

Upon launching the program, the scroll bars displayed initially are too small, as if the content size was much larger than it actually is:

enter image description here

When I start playing with, e.g., the vertical scroll bar, and bring it back to the original position at the top, it gets resized to its expected size (which corresponds to the ratio of scroll view and content view sizes):

enter image description here

(Notice the horizontal bar, which still has incorrect size. If I then play with it, and bring it back to its leftmost position, it gets resized to the correct size.)

3条回答
神经病院院长
2楼-- · 2019-07-06 17:36

I also encountered the same problem, I have searched everywhere but it seems no one else experiences this problem. Fortunately I found a hack which solves the problem.

What I did notice was that when the window is resized or maximized the scrollbars resize to the expected size (autoresizing has to be enabled). This is because when the window resizes so does the scrollview and the length of the scroll bars gets recalculated and is calculated correctly. Possibly due to some bug the scroll bar lengths are not calculated correctly on initialization. Anyway to fix the problem, in your application delegate create an outlet to your window. Override the "applicationDidFinishLaunching" method and inside it call the method "frame" on the window outlet, which returns the current NSRect of the window. Using the returned value add one to the size.width and size.height. The call the method setFrame with display set to YES. This will resize the window and force the size of the scrollbars to be recalculated.

Here is the code for applicationDidFinishLaunching Below

(void)applicationDidFinishLaunching:(NSNotification *)aNotification
{

     // Get the current rect
     NSRect windowRect = [_window frame];`

     // add one to the width and height to resize window
     windowRect.size.width += 1;
     windowRect.size.height += 1;

     // resize window with display:YES to redraw window subviews
     [_window setFrame:windowSize display:YES];

}
查看更多
We Are One
3楼-- · 2019-07-06 17:52

Building on the answer from jstuxx above, if you don't want the window to visibly resize, try:

NSRect windowRect = [[[self view] window] frame];
windowRect.size.width += 1;
windowRect.size.height += 1;
[[[self view] window] setFrame:windowRect display:YES];
windowRect.size.width -= 1;
windowRect.size.height -= 1;
[[[self view] window] setFrame:windowRect display:YES];

I had to put this code after where I was programmatically adding the scroll view to my interface.

查看更多
该账号已被封号
4楼-- · 2019-07-06 17:56

I encountered this issue when modifying an NSTextView textContainer size to toggle line wrapping. Resizing the enclosing view does cause the correct scroll view height to be used, however its a brutal solution.

NSScrollView supports -reflectScrolledClipView. Calling this directly in my case had no effect except when delayed on the runloop:

[textScrollView performSelector:@selector(reflectScrolledClipView:) withObject:textScrollView.contentView afterDelay:0];

The scroller position is correct but there is a scroller redraw. So it looks as if part of the view geometry is calculated when drawing. A better solution is therefore:

NSDisableScreenUpdates();
[textScrollView display];
[textScrollView reflectScrolledClipView:textScrollView.contentView];
[textScrollView display];
NSEnableScreenUpdates();
查看更多
登录 后发表回答