0
votes

Ok. I've been at this over and over. I've seen blogs and cocoa dev threads. I've seen Kyle Sluder's proposed solution, but have yet to find a solution that really works.

How can you position subviews of an NSScrollView with auto layout?

Is it just silently broken ? Nothing seems to work.

2
can you be more specific? What seems to be the problem with autolayout and NSScrollView.lead_the_zeppelin
Oh, the fact that nobody seems to have a way to to add Auto Layout constrained views to the document view of an NSScrollView without having ambiguous layout.uchuugaka
I can get where some things appear, but controlling constants and repositioning, stinks and is broken mostly. So, I've been building my own scrollview that is auto layout friendly. Only hard part is NSScroller really.uchuugaka

2 Answers

1
votes

Ok, old question, but this particular issue is a personal bugbear of mine so I'll answer it anyway!

The first thing to note is that an NSScrollView contains an NSClipView, which itself has a view outlet called documentView. These are all added for you when you drag a new scroll view into your storyboard or nib file. By default, the document view is an NSView called simply "View". If you're using a custom view, you can just select this and set its type in the inspector on the right to whatever you want. Otherwise, you'll be adding subviews to it.

The big thing that is easy to miss here is that, by default, the document view has its layout set to 'Translates Mask Into Constraints'. This is fine if the content size will never, ever change, and if that's the case you can simply set the frame of the document view to whatever you want and leave it at that. If you want it to automatically resize itself to fit its content however, there's a few things you'll need to do.

First off, that document view needs to have a completely unambiguous size. If you're using a custom view, I'd recommend giving it an intrinsicContentSize. You should also set 'Intrinsic Size' in IB's inspector to 'Placeholder' and give it a suitable value, or you'll get a bunch of autolayout warnings. If your document view gets its size from its content, all of the subviews must be linked in an unbroken chain from top to bottom, and from left to right, such that the content knows exactly how big it ought to be. This is quite an art in itself, so I won't go into it. A simple example where you have only one subview would be to pin its top, bottom, leading and trailing constraints to its parent, but as noted above if you're doing this, you might as well just set the type of the document view.

Now the fun bit. Select your document view and set its layout to 'Automatic'. Next, add top, bottom, leading and trailing constraints to its superview with a suitable value. I'm using zero, but you might want a small border. Finally, select the TRAILING and BOTTOM constraints you just made and set them to '>=' (greater than or equal) and a priority of 500 or less. The priority is very important, as it has to be less than the priority that the clip view uses to determine its own minimum size. Too high and the clip view will be forced to remain larger than its content, making it impossible in turn for the scroll view to be smaller than its content, rendering it useless.

The technical details aren't important. Just remember to set the document view to layout: automatic, pin all edges, and make the trailing and bottom constraints >= and priority 500.

Note that this will cause your content to hug the top-left corner.

0
votes

Have you tried setting the document view's setTranslatesAutoresizingMaskIntoConstraints to TRUE?

[_scrollView.documentView setTranslatesAutoresizingMaskIntoConstraints:YES];