【问题标题】:How can I get NSScrollView to respect a clipping path如何让 NSScrollView 尊重剪切路径
【发布时间】:2011-07-13 05:06:30
【问题描述】:

我正在尝试制作一个带有剪角的 NSScrollView,类似于 Twitter 应用:

我有一个NSScrollView 子类,我添加了以下代码:

- (void)drawRect:(NSRect)dirtyRect {
    NSBezierPath *pcath = [NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:kDefaultCornerRadius yRadius:kDefaultCornerRadius];
    [path setClip];

    [super drawRect:dirtyRect];
}

我希望NSScrollView 的内容具有圆角,但它不尊重剪切路径。我怎样才能做到这一点?




更新和澄清
我知道如何制作自定义NSScroller,我知道如何使其透明覆盖。我要问的是如何使NSSCrollView 夹角,包括它包含的所有内容。 NSScrollView 位于 NSView 内,其背景可能会发生变化,这意味着不能选择使用视图覆盖来伪造圆角。

【问题讨论】:

  • drawRect 的超实现声明有可能设置了一个新闻剪辑。尝试一个一个地绘制零件,而不是调用 super 看看是否会改变任何东西。
  • 你的意思是自己绘制 contentView 和 documentView 而不是让 super 来做?看来我必须重新实现所有 NSScrollView 滚动逻辑才能做到这一点。我希望有一种无需重新发明轮子的方法。
  • 查看 NSScroller 的文档。通常一个 NSScrollView 会有两个 NSScroller,一个 x 和一个 y。 NSScroller 类公开了绘图方法。如果你想要和 twitter 客户端一样的外观,无论如何你都必须继承 NSScroller。
  • 您的 cmets 与问题无关。我已经实现了一个自定义滚动条并且知道如何绘制这些部分。我不知道该怎么做是通过遵守 clippedPath 来确保 documentView 得到圆角。
  • 抱歉,从您的问题中不清楚您取得了多大的进步。我对此进行了一些尝试,很明显您必须将 NSClipView 或底层文档视图子类化才能使其正常工作。

标签: cocoa subclass rounded-corners nsscrollview nsbezierpath


【解决方案1】:

经过一番折腾,我刚刚发现 NSScrollView 可以通过简单地给它一个支持层并设置该层的圆角半径来制作圆角如果你也可以这样做它是内部的NSClipView。两者都是必需的,这很有意义,因为实际上是剪辑视图为NSScrollView 的文档视图提供了可视窗口。

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

【讨论】:

  • 但是请注意,这似乎不适用于包含 NSTextView 的 NSScrollView。在这种情况下,我们需要恢复到掩蔽层方法。
【解决方案2】:

您可以将遮罩应用到视图的图层:

[myScrollView setWantsLayer: YES];
[myScrollView layer].mask = ...;

面具是另一个CALayer。因此,在这种情况下,您将创建一个CALayer,将其背景颜色设置为不透明,设置其边界以匹配滚动视图,并为其指定cornerRadius,例如8.0

结果将是滚动视图及其所有内容似乎被屏蔽为一个圆角半径为 8px 的圆形矩形。

【讨论】:

  • 这似乎行得通,但我需要更多的灵活性。我只需要两个圆角,上面的圆角代码只是一个例子。不仅如此,当我在滚动视图上执行此操作时,所有内部内容都停止绘制,我不确定如何在不使用 drawRect 的情况下重新创建它。
  • 您可以将遮罩层的内容属性设置为几乎任何内容。看看Core Animation Cookbook——它应该可以帮助你绘制Core Animation。 (不幸的是,手边没有 URL。)
  • 这行得通,但带来了很多额外的问题(滚动视图中的 nsview 闪烁、剪裁角中出现奇怪的伪影以及实时调整图层大小的问题)。我希望有另一个答案,因为这样做所需的努力似乎相当大。这是我在此实现中看到的问题的简短截屏:screencast.com/t/wKt5vCjoWPu
  • 我也使用过这种方法,并且它“有点”有效。虽然似乎有工件,并且取决于视图层次结构中的其他内容。此外,如果您使用多个掩码,例如在共享边界的超级视图中,掩码之间似乎存在一些复合效果。我建议向 Apple 提交错误报告,并请求能够通过标准的 CALayer 方法对 NSScrollView 进行舍入,即为其提供支持层并设置其 cornerRadius 属性。似乎有不少有用的应用程序用于圆角NSScrollView
【解决方案3】:

您是否尝试过覆盖

- (BOOL)isOpaque {
  return NO;
}

并将滚动视图的-setDrawsBackground: 设置为NO 并保持视图不进行裁剪并使用[NSColor clearColor] 绘制角,因为这也会清除底层颜色并模拟圆形效果。

【讨论】:

  • 只需阅读您更新的要求“可能会改变的背景”,所以我想我的答案已经过时了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 2014-10-14
  • 2018-07-18
相关资源
最近更新 更多