Centering image view in scroll view


Steve Mills
 

Ack. I'm having a hard time figuring out how to make an NSImageView in an NSScrollView act like it does in Preview.app, where it will stay centered within the window when any axis is smaller than the window, but still be zoomable by the user. What magic combination of settings, methods, and/or constraints do I need?

I have an NSViewController, if I need to override some methods there. Its view contains the scroll view. I initially want the image to fit within the window, so I calculate and set the scroll view's magnification in viewWillAppear.

Steve via iPhone


Quincey Morris
 

On Nov 16, 2017, at 08:04 , Steve Mills <sjmills@...> wrote:

I'm having a hard time figuring out how to make an NSImageView in an NSScrollView act like it does in Preview.app, where it will stay centered within the window when any axis is smaller than the window, but still be zoomable by the user. What magic combination of settings, methods, and/or constraints do I need?

I don’t think there’s any magical solution. From what I see in Preview, it has a 2-phase approach — it lets you zoom normally via a pinch gesture (that is, doesn’t force any centering), then fixes the centering when you let go.

However, figuring it out is a bit complicated, because you’ve at least got these things going on:

— Is it resizing the image within the image view, or the image view within the scroll view, or both?

— To get “gray” areas around the image when the image/image view is smaller than the window/scroll view, you may need a container view for the image view. (In a scroll view, if the document view is smaller than the clip view, I don’t think you can reliably control where in the clip view the document view appears. You need the container to be at least the size of the clip view, so you can position the actual content within it.)

— There’s a difference between zooming and scaling. A scroll view’s zooming takes the document view and applies a transform to it. Scaling renders the document view at a higher resolution for a larger size.

In the old days, I did this manually by observing the clip view’s frame and bounds change notifications, and manually resizing and repositioning the document view to get the right result. It’s ugly, and it’s easy to end up with a cascading cycle notifications, but it’s doable. It’s not clear to me whether autolayout is any help.


Graham Cox
 

You need to subclass NSClipView and implement the behaviour there. It’s annoying that there’s no built-in solution since it’s an ‘obvious’ requirement to me.

The better news is that the needed behaviour isn’t hard to achieve - this stack overflow answer gives a good solution: https://stackoverflow.com/questions/22072105/how-do-you-get-nsscrollview-to-center-the-document-view-in-10-9-and-later


—Graham

On 17 Nov 2017, at 3:04 am, Steve Mills <sjmills@...> wrote:

Ack. I'm having a hard time figuring out how to make an NSImageView in an NSScrollView act like it does in Preview.app, where it will stay centered within the window when any axis is smaller than the window, but still be zoomable by the user. What magic combination of settings, methods, and/or constraints do I need?

I have an NSViewController, if I need to override some methods there. Its view contains the scroll view. I initially want the image to fit within the window, so I calculate and set the scroll view's magnification in viewWillAppear.