Clipping rounded corners on a NSScrollView - cocoa

I have a simple custom borderless NSWindow subclass which has a rounded rectangle shape.
In the content view of this window, I've added an NSScrollView.
How do I get the NSScrollView to clip its document view to the rounded rectangle shape of the NSWindow?
I've tried subclassing the NSScrollView, overriding drawRect: and adding a clipping path before calling super. I've also tried subclassing the document view and the clip view with the same technique but I cannot get it to clip.
BTW, this is on Lion with the elastic scrolling behaviour.

After much fiddling, I just discovered that NSScrollView's can be made to have rounded corners by simply giving it a backing layer and setting that layer's corner radius provided you also do the same to it's internal NSClipView. Both are required, which now makes sense, since it's the clip view that actually provides the viewable window into the NSScrollView's document view.
NSScrollView * scrollView = ...;
// Give the NSScrollView a backing layer and set it's corner radius.
[scrollView setWantsLayer:YES];
[scrollView.layer setCornerRadius:10.0f];
// Give the NSScrollView's internal clip view a backing layer and set it's corner radius.
[scrollView.contentView setWantsLayer:YES];
[scrollView.contentView.layer setCornerRadius:10.0f];

Even better IMO:
scrollView.wantsLayer = true
scrollView.layer?.masksToBounds = true
scrollView.contentView.wantsLayer = true
scrollView.contentView.layer?.masksToBounds = true

In Swift I have solved like this:
scrollView.wantsLayer = true
scrollView.contentView.wantsLayer = true
scrollView.layer?.cornerRadius = 20.0
scrollView.contentView.layer?.cornerRadius = 20.0

Related

Draw shadow of layer-backed NSView beyond bounds

I'd like to get a custom NSShadow on a borderless NSWindow,
and since I'm also applying some animations on the window, I've set up the window's content view to be layer-backed.
When applying the NSShadow on the contentView, the shadow is clipped at the view's border:
One possibility would be to reduce contentView's rect (NSInsetRect), but then the NSWindow's resizing borders wouldn't match the window's appearance!
Is there any chance to draw the layer's shadow beyond its borders?
EDIT: The shown screenshot already has a -10 inset rect!

Hide NSView overflow

I'm a web dev guy. The overflow:hidden CSS property tells the render engine to not draw the current view's content across the parent's borders.
In my current project, I have a custom NSWindow with a custom NSView with rounded corners by using NSMakeRect, overwriting drawRect: and so on. A WebView inside the NSView is strechted across the entire NSView frame.
Now the WebView 'overflows' the rounded corners of theNSView`. What I do like to have is that the WebView has the same mask as the NSView.
How would you do that?
Also make sure your view sets clips subviews to true. As far as I understand you, this is what you are looking for, and prevents f.ex. images to reach out of the parent view.
[self.view setClipsToBounds:YES];
You can set a corner radius to the layer of a view.
myView.layer.cornerRadius = 5.0f;
You'll have to add QuartzCore.framework.

NSView free-angle rotation

I have NSView container (with NSImageView and some other custom subviews). How to set its rotation properly? I tried to set angle through setFrameRotation: and set rotation matrix in views layer. But in these cases subview image becomes downscaled and clipped.
Update:
If I set rotation via [myView setFrameRotation: angle]:
almost fine, except text frame (drawing via [NSString drawAtPoint:...] and rotation anchor is at left-bottom corner (I want at bottom-center, [myView setFrameOrigin:...] does nothing)
If I set rotation via myView.layer.transform = CATransform3DMakeRotation (angle, 0, 0, 1):
frame bound remains unrotated and clips subviews (but this approach is more suitable for view container)

UIView backed by CATiledLayer in UIScrollView doesn't scroll initially

I'm adding a CATiledLayer backed UIView in UIScrollView.
When the view is first loaded, I'm trying to fit the UIView, by setting the zoomScale of UIScrollView - this fits the UIView and the layered contents.
I'm having a method to fetch the tiles of image and I'm rendering them in drawLayer:inContext:
Now even if the contentsize of scrollview/frame of CATiledLayer view is greater than UIScrollView, it doesn't scroll initially.
The moment I try to zoom by pinching the screen, I'm able to scroll perfectly.
I can't scale the CGContext in drawLayer:inContext, since the context I receive is of a tile and not whole image and I have 20 tiles which make up my image.
At the end of the initWithFrame of the PDFScrollView i added the line:-
self.zoomScale = 1.0;
This worked for me.
The code is pretty much doing the same stuff as apple example
http://developer.apple.com/library/ios/#samplecode/ZoomingPDFViewer/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40010281-Intro-DontLinkElementID_2
which also doesnt scroll on loading

How can I get NSScrollView to respect a clipping path

I am trying to make a NSScrollView with clipped corners, similar to the Twitter app:
I have a NSScrollView subclass which I added the following code:
- (void)drawRect:(NSRect)dirtyRect {
NSBezierPath *pcath = [NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:kDefaultCornerRadius yRadius:kDefaultCornerRadius];
[path setClip];
[super drawRect:dirtyRect];
}
I expected the content of the NSScrollView to have rounded corners, but it is not respecting the clipped path. How can I do this?
UPDATE & CLARIFICATION
I know how to make a custom NSScroller, I know how to make it transparent overlay. All I am asking is how to make the NSSCrollView clip its corners, including everything it contains. The NSScrollView is inside a NSView which has a background that could change, meaning a view overlay to fake the rounded corners is not an option.
After much fiddling, I just discovered that NSScrollView's can be made to have rounded corners by simply giving it a backing layer and setting that layer's corner radius provided you also do the same to it's internal NSClipView. Both are required, which now makes sense, since it's the clip view that actually provides the viewable window into the NSScrollView's document view.
NSScrollView * scrollView = ...;
// Give the NSScrollView a backing layer and set it's corner radius.
[scrollView setWantsLayer:YES];
[scrollView.layer setCornerRadius:10.0f];
// Give the NSScrollView's internal clip view a backing layer and set it's corner radius.
[scrollView.contentView setWantsLayer:YES];
[scrollView.contentView.layer setCornerRadius:10.0f];
You can apply a mask to a view's layer:
[myScrollView setWantsLayer: YES];
[myScrollView layer].mask = ...;
The mask is another CALayer. So in this case you'd create a CALayer, set its background colour to opaque, set its bounds to match the scrollview, and give it a cornerRadius of, say, 8.0.
The result would be that the scroll view and all its contents would appear to be masked to a roundrect with a corner radius of 8px.
Have you tried overriding
- (BOOL)isOpaque {
return NO;
}
And setting the scroll view's -setDrawsBackground: to NO and just leave the view without clipping and just draw the corners with [NSColor clearColor] since this will also clear the underlying color and simulate a round effect.

Resources