How can I get NSScrollView to respect a clipping p

2020-03-07 07:01发布

问题:

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.

回答1:

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.



回答2:

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];


回答3:

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.