CALayer "floating" within NSScrollView? - calayer

I'd like to have a CALayer "float" over my scroll view's documentView. That is, it shouldn't move during scrolling.
If I add a CALayer to my NSSCrollView's layer, the added layer is masked by the clipview: in only shows where the scrollers are.
Adding the layer to the clipview doesn't work either. It's masked.
I could add the layer to the document view and compensate the scrolling so that it stays in place, but that would be inelegant.

As it turns out, the solution was simple.
The layer was masked by the scrollview's subviews (namely, its contentView). I simply changed the layer zPosition property to a positive value, and the layer now shows.

Related

If a NSView uses autolayout, do all of its subviews also need to use autolayout for positioning?

I have a view in a window, the position and size of the view are calculated with autolayout. The view has a subview, a draggable NSView subclass. It is really easy to make a NSView "draggable" by overriding -mouseDown: and -mouseDragged: and changing the frame of the view directly.
The view hierarchy is as follows,
What is the best way of making the subview draggable in this case?
For example,
Is it possible for the subview to not use autolayout, so that it can be positioned by changing the frame directly? i.e. the window positions the main view, but then autolayout does not layout the subview inside the main view. Or do all views in the hierarchy need to use autolayout?
When I have used autolayout before, I have used it to make "fixed" layout that respond to resizing. But dragging a view with a mouse does't seems like a natural use-case for autolayout.
Is it possible for the subview to not use autolayout, so that it can be positioned by changing the frame directly?
Yes. If you keep translatesAutoresizingMaskIntoConstraints turned on, it automatically creates constraints from the values of frame and autoresizingMask.
In fact, this means it will use Auto Layout, but you can work with frame just like with manual positioning.
The best way is to not avoid auto layout.
Making a view draggable is pretty easy with auto layout constraint IBOutlets and getting the mouse delta from NSEvent short circuit mouse tracking.

Shrink NSScroller of NSScrollView in layer-backed view

I'm experiencing a weird problem (Bug?): Say I have a WebView, which will scroll vertically.
I now want to shrink the mainFrame's vertical scroller a little bit, so that its height is smaller than the NSScrollView itself.
The reason for this is that I want to pin two views (on top and on bottom edge) above the webview.
I did that easily in the frameLoad delegate method by altering the verticalScroller's frame (altering origin and height).
It works, but:
However once I set the webView and it's parent NSView to be layer-backed, it stops working, the scroller resets itself to the default position and height.
Now I don't know if this is a bug or not.
Is there any other way I could try to 'inset' the scroller?
Have you tried subclassing NSScroller, setting it as the vertical scroller for your NSScrollView and overriding
-(void) setFrameOrigin:(NSPoint)origin;
-(void) setFrameSize:(NSSize)size;
I assume making the NSView layer-backed causes frameSize to be set again(NSScrollView seems to take quite a bit of control on this because when you create a custom scroller, there is no "clean" way to set an NSScroller as horizontal or vertical other than calling -initWithFrame: with
height > width to automatically set it as vertical
width > height to automatically set it as horizontal
My other suggestion would be, if you want the NSScroller to not fully reflect the size of its parent NSScrollView would you be better off having an NSView as the content view of the webview. And the NSView have 3 subviews. Two views at the top and bottom pinned, and one NSScrollView in the middle. No custom NSScroller necessary in this case.

NSScrollView and ScrollToPoint on an NSImage

I have a NSView as the documentView for a NSScrollView. I also have a NSImageView as a subview of the NSView. The image dynamically changes size so the scroll bars become active/inactive at various times. Once the image has changed, I'd like to scroll to a certain point on the image. From within the NSView's drawRect: method, I call
[[myScrollView contentView] scrollToPoint: myPoint];
The scroll bars update and the image appears as I'd like, but as soon as the image is scrolled, a double image appears or parts of the image get cut off. Any help would be appreciated. Thank you.
Sounds like you might want to turn off the "Copy On Scroll" behavior option of the NSScrollView either in Interface Builder or programmatically.
From Scroll View Programming Guide for Mac OS X: How Scrolling Works:
The NSClipView class provides low-level scrolling support through the
scrollToPoint: method. This method translates the origin of the
content view’s bounds rectangle and optimizes redisplay by copying as
much of the rendered document view as remains visible, only asking the
document view to draw newly exposed regions. This usually improves
scrolling performance but may not always be appropriate. You can turn
this behavior off using the NSClipView method setCopiesOnScroll:
passing NO as the parameter. If you do leave copy-on-scroll active, be
sure to scroll the document view programmatically using the NSView
method scrollPoint: method rather than translateOriginToPoint:.

Using CALayer as a background for other NSViews

I have an application with an NSTableView in a window. I want to use a CALayer as the background for the entire window, and the table view. In all my my experiments so far, the CALayer always draws over the NSTableView, which is not the effect I'm looking for. Is there a way to make this work, or am I simply out of luck due to the nature of layer-hosting views vs NSViews?
My test setup is a window with the usual NSScrollView/NSTableView combo, and a sibling NSView behind it in the view order. The NSView is set to be layer-hosting with my custom layer within it (just a layer with a backgroundColor set). I've experimented with setting the window's content view to be layer-backed, as well as the table view itself, as well as wrapping the NSScrollView in a layer-backed NSView. The result is always the same.
Thanks for any insight you might be able to provide.
It is simple. all overlapping views or layers should be layer backing or layer hosting for correct ordering.
you can set [tableview setWantsLayer:YES]
or simply check it in the layers tab when editing the interface.

NSView controls not resizing?

I have a NSView with a NSTableView inside of it.
If the view looks like this:
And the size & position properties for the Scollview (and tableview) look like this:
Then why when I resize the view, does it look like this:
Are my autosizing properties not set correctly? To my understanding they should be?
To make it clearer, you won’t see autoresizing behaviour whilst designing your view in Interface Builder unless the border of the subview coincides with the corresponding border of the superview and Live Autoresizing is enabled.
This behaviour exists because resizing the superview can be used to indicate that you want a certain margin between the subview area and the superview area — for instance, you might have a 100pt margin between the subview’s right border and the superview’s right border, and then increase that margin to, say, 200pt by dragging the superview handles.
Edit: On the other hand, if you want to resize the superview whilst keeping the margins according to the autoresizing mask, you can drag the superview handles whilst holding the alt/option key.
Use Cocoa Simulator (File -> Simulate Interface) in order to test your interface, including autoresizing behaviour.
The table with its scroll view will autoresize to your view's size only if you enter dimensions in by hand in Size info panel. They will not autoresize if you drag view's handles with mouse.

Resources