Re: guidelines for using autolayout with NSScrollView?
Re: guidelines for using autolayout with NSScrollView?
- Subject: Re: guidelines for using autolayout with NSScrollView?
- From: Chuck Soper <email@hidden>
- Date: Sat, 16 Mar 2013 17:33:07 -0700
- Thread-topic: guidelines for using autolayout with NSScrollView?
On 3/16/13 3:05 PM, "Kyle Sluder" <email@hidden> wrote:
>On Mar 16, 2013, at 12:46 PM, Chuck Soper <email@hidden> wrote:
>
>> Are there similar notes on how to use autolayout with NSScrollView? Does
>> anyone know the specific details on what Apple recommends? For example,
>> are both mixed and pure autolayout approaches okay with NSScrollView?
>>(The
>> mixed or pure autolayout terminology comes from the UIScrollView notes -
>> link above.)
>
>There is no official recommendation, but I have had a *lot* of experience
>in this area. And I've been meaning to write a blog post about this as a
>follow-up to my Xcoders presentation on auto layout, so consider this a
>draft!
>
>The biggest issue with using auto layout in an NSScrollView's document
>view is that NSScrollView itself is completely unaware of auto layout.
>Thus, it relies on the behavior provided by setting
>translatesAutoresizingMaskIntoConstraints=YES on its subviews so it can
>continue to use -setFrame: to position them even if auto layout is turned
>on for the window.
>
>At this point it's worth noting another difference between NSScrollView
>and UIScrollView: UIScrollView directly manipulates its own bounds.origin
>to perform scrolling of its entire subview hierarchy. The contentSize
>property dictates the size of the scrollable region.
>
>NSScrollView, on the other hand, doesn't actually do any scrolling on its
>own: it delegates that responsibility to an NSClipView. The scroll view
>positions the clip view and scrollers (if they are visible) using
>-setFrame:. Rather than exposing a contentSize property, NSClipView
>observes the frame of _one specific subview_ called its documentView.
>This view's frame.size becomes the equivalent of UIScrollView's
>contentSize.
>
>In order to perform scrolling correctly, the documentView's frame.origin
>must lie at (0,0) in the clip view's bounds coordinate system.
>NSClipView, like NSScrollView, is unaware of auto layout, so it uses
>-setFrameOrigin: to put the document view at (0,0). If auto layout gets
>turned on for the window, this position gets turned into a pair of
>constraints with a priority of 1000 (required).
>
>Two more constraints will be synthesized to define the width and height
>of the document view. These constraints are the problem. In either
>direction, one of two kinds of constraints will be generated, depending
>on the documentView's autoresizing mask for that direction:
>
>1. If the view is stretchable in that direction, a constraint will be
>installed relating the opposing edge of the documentView to the edge of
>the superview.
>
>2. If the view is not stretchable in that direction, a constraint will be
>installed dictating the absolute value of the documentView's frame.size
>in that dimension.
>
>Like all autoresizing-mask constraints, these constraints are required
>(priority 1000). Because the entire constraint system is solved at once,
>it should be intuitive that any constraints that attempt to influence the
>size of the documentView will conflict with either the constraints
>installed by the clip view on the documentView and/or with the
>constraints installed by the scroll view on the clip view.
>
>So we have a dilemma. We need to somehow break the bidirectionality of
>the relationship between the clip view and the documentView. There is no
>straightforward way to express this using the constraints API, but it is
>indeed possible without resorting to mucking with private internal
>details.
>
>In other words, we want to somehow run layout of arbitrary constraints on
>our documentView's subtree and retrieve the resultant frame of the
>documentView without involving the documentView itself in our constraint
>system. Once we have the right values, we can use -setFrameSize: on the
>documentView; the clip view will notice and it will update its scrollable
>area.
>
>The way we accomplish this is to install another view in our subtree and
>define all our constraints relative to _that_ view. I'm going to call
>this the adaptor view. The documentView installs constraints to keep the
>adaptor view's top and leading margins equal to zero, but critically it
>does NOT install any constraints on the trailing or bottom edges. This
>leaves the adaptorView's width and height free to be defined by its
>content's layout.
>
>The documentView signs up for frame change notifications from the adaptor
>view. Whenever it changes its frame, the documentView calls [self
>setFrameSize:] with the same size. Then the clip view hears about this,
>and the scroll view reflects the correct document size. For this to work,
>the documentView's autoresizing mask should be set to width and height
>NON-stretchable, that way when the clip view resizes (perhaps during
>window dragging) it doesn't resize your documentView.
>
>If you're laying out the contents of your scroll view in IB, the most
>convenient approach is to make the adaptor view the only subview of your
>documentView, and to add all your widgets as subviews of the adaptor
>view. The bonus here is that if your constraints are insufficient to
>fully specify the frame of the adaptor view, IB will doggedly insist on
>adding margin or fixed-size constraints until you fix your layout. Yes,
>we have turned one of IB's most annoying habits into a feature!
>
>If you're generating all your constraints in code, however, it might be
>just as convenient to make your adaptor view a _sibling_ of all your
>widgets and to call -setHidden:YES on it, thus removing a level of
>hierarchy between the documentView and your widgets.
This is an excellent in-depth description and a great follow-up to your
Seattle Xcoders talk from last January. You described your solution at the
Seattle Xcoders meeting as a bit of a hack. Would you describe this
revised approach as more stable.
I've seen a number of developers on cocoa-dev and stack overflow that
describe less-involved solutions such as just adding a couple of
constraints to the clip view. On the other hand, I've never been able to
implement those easier solutions in my own code.
I really wish that Apple could provide official guidance with a tech note
and/or some sample code. A lot of people are using auto layout with
NSScrollView. Others are avoiding auto layout.
>>
>> I think that autolayout is a great technology.
>
>Me too, but it will be even better when AppKit fully supports it. All the
>logic I described above could be added to NSClipView, and suddenly
>NSScrollView would be constraint-aware.
>
>Let's see what 10.9 brings.
>
>--Kyle Sluder
Should we file radars to be more proactive?
Chuck
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden