如何使用 NSVisualEffectView 制作平滑、圆润、类似体积的 OS X 窗口?

2024-02-03

I'm currently trying to make a window that looks like the Volume OS X window:
enter image description here


为了做到这一点,我有自己的NSWindow(使用自定义子类),它是透明的/无标题栏/无阴影的,有一个NSVisualEffectView在它的 contentView 里面。这是我的子类的代码,用于使内容视图变圆:

- (void)setContentView:(NSView *)aView {
   aView.wantsLayer            = YES;
   aView.layer.frame           = aView.frame;
   aView.layer.cornerRadius    = 14.0;
   aView.layer.masksToBounds   = YES;

   [super setContentView:aView];
}


And here's the outcome (as you can see, the corners are grainy, OS X's are way smoother):
enter image description here
Any ideas on how to make the corners smoother? Thanks


OS X El Capitan 更新

我在下面的原始答案中描述的 hack 在 OS X El Capitan 上不再需要了。这NSVisualEffectView’s maskImage应该在那里正常工作,如果NSWindow’s contentView被设置为NSVisualEffectView(如果它是子视图,这是不够的contentView).

这是一个示例项目:https://github.com/marcomasser/OverlayTest https://github.com/marcomasser/OverlayTest


原始答案 – 仅与 OS X Yosemite 相关

我找到了一种通过重写私有 NSWindow 方法来做到这一点的方法:- (NSImage *)_cornerMask。只需返回通过绘制带有圆角矩形的 NSBezierPath 创建的图像即可获得类似于 OS X 的音量窗口的外观。


在我的测试中,我发现您需要为 NSVisualEffectView 使用遮罩图像andNSWindow。在您的代码中,您正在使用视图的层cornerRadius属性来获取圆角,但您可以通过使用蒙版图像来实现相同的目的。在我的代码中,我生成一个 NSImage,供 NSVisualEffectView 和 NSWindow 使用:

func maskImage(#cornerRadius: CGFloat) -> NSImage {
    let edgeLength = 2.0 * cornerRadius + 1.0
    let maskImage = NSImage(size: NSSize(width: edgeLength, height: edgeLength), flipped: false) { rect in
        let bezierPath = NSBezierPath(roundedRect: rect, xRadius: cornerRadius, yRadius: cornerRadius)
        NSColor.blackColor().set()
        bezierPath.fill()
        return true
    }
    maskImage.capInsets = NSEdgeInsets(top: cornerRadius, left: cornerRadius, bottom: cornerRadius, right: cornerRadius)
    maskImage.resizingMode = .Stretch
    return maskImage
}

然后我创建了一个 NSWindow 子类,它有一个遮罩图像的设置器:

class MaskedWindow : NSWindow {

    /// Just in case Apple decides to make `_cornerMask` public and remove the underscore prefix,
    /// we name the property `cornerMask`.
    @objc dynamic var cornerMask: NSImage?

    /// This private method is called by AppKit and should return a mask image that is used to 
    /// specify which parts of the window are transparent. This works much better than letting 
    /// the window figure it out by itself using the content view's shape because the latter
    /// method makes rounded corners appear jagged while using `_cornerMask` respects any
    /// anti-aliasing in the mask image.
    @objc dynamic func _cornerMask() -> NSImage? {
        return cornerMask
    }

}

然后,在我的 NSWindowController 子类中,我设置了视图和窗口的遮罩图像:

class OverlayWindowController : NSWindowController {

    @IBOutlet weak var visualEffectView: NSVisualEffectView!

    override func windowDidLoad() {
        super.windowDidLoad()

        let maskImage = maskImage(cornerRadius: 18.0)
        visualEffectView.maskImage = maskImage
        if let window = window as? MaskedWindow {
            window.cornerMask = maskImage
        }
    }
}

我不知道如果你向 App Store 提交带有该代码的应用程序,Apple 会做什么。您实际上并没有调用任何私有 API,您只是重写了一个恰好与 AppKit 中的私有方法同名的方法。您如何知道存在命名冲突? ????

此外,这会优雅地失败,而您无需执行任何操作。如果苹果改变了它内部的工作方式,并且该方法不会被调用,你的窗口就不会得到漂亮的圆角,但一切仍然可以工作并且看起来almost相同。


如果你好奇我是如何发现这个方法的:

我知道 OS X 音量指示做了我想做的事情,我希望像疯子一样改变音量会导致将音量指示显示在屏幕上的进程显着占用 CPU。因此,我打开了活动监视器,按 CPU 使用率排序,激活过滤器以仅显示“我的进程”,并敲击音量增大/减小键。

很明显,coreaudiod和一个叫做BezelUIServer in /System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/BezelUI/BezelUIServer做了某事。从后者的捆绑资源来看,很明显它负责绘制音量指示。 (注意:该进程仅在显示某些内容后运行一小段时间。)

然后,我使用 Xcode 在该进程启动后立即附加到该进程(“调试”>“附加到进程”>“按进程标识符 (PID) 或名称...”,然后输入“BezelUIServer”)并再次更改音量。连接调试器后,视图调试器让我查看视图层次结构,并看到该窗口是名为 NSWindow 子类的实例BSUIRoundWindow.

Using class-dump https://github.com/nygard/class-dump二进制文件显示该类是 NSWindow 的直接后代,仅实现三个方法,而其中一个是- (id)_cornerMask,这听起来很有希望。

回到 Xcode,我使用对象检查器(右侧,第三个选项卡)来获取窗口对象的地址。使用该指针我检查了这是什么_cornerMask实际上通过在 lldb 中打印其描述来返回:

(lldb) po [0x108500110 _cornerMask]
<NSImage 0x608000070300 Size={37, 37} Reps=(
    "NSCustomImageRep 0x608000082d50 Size={37, 37} ColorSpace=NSCalibratedRGBColorSpace BPS=0 Pixels=0x0 Alpha=NO"
)>

这说明返回值实际上是一个NSImage,这就是我需要实现的信息_cornerMask.

如果您想查看该图像,可以将其写入文件:

(lldb) e (BOOL)[[[0x108500110 _cornerMask] TIFFRepresentation] writeToFile:(id)[@"~/Desktop/maskImage.tiff" stringByExpandingTildeInPath] atomically:YES]

要更深入地挖掘,您可以使用料斗拆装机 http://www.hopperapp.com拆解BezelUIServer and AppKit并生成伪代码来看看如何_cornerMask的实现和使用是为了更清楚地了解内部结构是如何工作的。不幸的是,与此机制有关的所有内容都是私有 API。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 NSVisualEffectView 制作平滑、圆润、类似体积的 OS X 窗口? 的相关文章

  • 在 iOS4 中视图控制器即将弹出时收到通知

    这个问题以前有人问过 但我能找到的答案是 2009 年的 不适合我的问题 让我重申一下这个问题 我有一个UINavigationController产生并推动许多不同的UIViewControllers 入栈 其中之一涉及一些核心数据操作
  • 如何将 NSString 值 @"3.45" 转换为浮点数?

    如何将 NSString 值 3 45 转换为浮点数 3 45 float fCost NSDecimalNumber decimalNumberWithString 3 45 floatValue NSString val 3 45 fl
  • 安装 libjpeg v8 到 /opt/local

    如何在 OSX 上将 libjpeg 8 安装到 opt local 我问的原因是我想用以下方法制作大脑活动的小电影MNE C 库 http www nmr mgh harvard edu martinos userInfo data MN
  • 使用 WebRTC 构建 iOS 本机应用程序

    我找了4天了 还是没找到 我构建了所有库并将其集成到我的自定义项目中 但我不知道应该采取哪些步骤才能使其正常工作 我在代码示例 解释中发现的唯一内容是 tech appear in 2015 05 25 Getting started wi
  • 如何在 OS X 上查看 $PATH 变量的当前值?

    PATH returns bash usr local share npm bin Library Frameworks Python framework Versions 2 7 bin usr local bin usr local s
  • 如何在 iOS 上捕获的视频中添加水印[重复]

    这个问题在这里已经有答案了 我想知道是否有人可以告诉我如何实现这一目标 如果一直在考虑几个解决方案 从捕获的视频创建单独的图像 然后将它们合并到每个图像中 然后创建一个新的 AVAsset 听起来有点复杂 您不觉得吗 合并2个视频 一个是透
  • 如何使用 MPMusicPlayerController 播放音乐?

    任何人都可以建议我如何在我的应用程序中使用 MPMusicPlayerController 播放音乐 任何人的帮助将不胜感激 谢谢你 莫尼什 创建一个MPMediaPickerController这样你就可以从 iPod 中选择一些音乐 然
  • 将 UIPanGestureRecognizer 添加到 UIScrollView 时禁用滚动

    我有一个滚动视图 我想让它在平移完成时消失 它工作正常 平移时滚动视图消失 但问题是现在我无法滚动内容 UIView animateWithDuration 0 2 delay 0 2 options UIViewAnimationCurv
  • 如何在iPhone中将字节数组转换为base64字符串?

    我有一段vb代码 我需要将字节数组转换为 Base 64 字符串 下面是vb代码 如果 arrLicence Count gt 0 那么 LicenseBytes CType Array CreateInstance GetType Byt
  • 从哪里开始使用适用于 Retina 显示屏的 OpenGL 绘制程序

    我知道由于这里提到的错误 我无法将 GLPainter 示例从苹果适应到视网膜 在 Retina iPad 上显示全屏 CAEAGLLayer 时出现问题 https stackoverflow com questions 9757052
  • iOS 中系统日期更改后如何更改带有日期的标签?

    我有一个简单的查询 但不知道该怎么做 这就是我想要实现的目标 1 我有一个带有今天日期的 UILabel 即 29 04 12 2 在午夜 我希望该标签自行更新为 30 04 12 而无需更改视图或按任何内容 这是第2步 我不知道该怎么做
  • 如何在基于视图的应用程序中添加导航控制器

    我想向基于视图的应用程序添加导航控制器 我们如何以编程方式和使用 xib 文件来完成此操作 如果您需要在 uiviewcontroller 中合并导航控制器 您需要按如下方式初始化它 UIViewController yourViewCon
  • 如何知道两个 NSDate 是否在同一天

    你知道如何知道两个NSDate是同一天 我想考虑到区域设置 使用a可能很容易timeIntervalSinceDate 但星期一 23H58 和星期二 00H01 不在同一天 处理NSDate和计算区域设置不是很容易 NSCalendar
  • “EXC_BAD_ACCESS”与“分段错误”。两者实际上相同吗?

    在我的前几个虚拟应用程序 用于学习时练习 中 我遇到了很多EXC BAD ACCESS 这以某种方式告诉我错误访问是 您正在触摸 访问一个不应该的对象 因为它尚未分配或释放 或者只是您无权访问它 查看此示例代码 该代码存在访问错误问题 因为
  • UIAlertAction 处理程序在延迟后运行

    我正在尝试将 UIAlertViews 更改为 UIAlertControllers 我为此设置了这个操作 UIAlertAction undoStopAction UIAlertAction actionWithTitle Undo St
  • 当表格为空时 iPhone UITableView 图像背景

    我想当我的 UITableView 为空时显示图像背景 目前 我尝试将 UIImageView 添加到包含表格的视图控制器 但 XCode 不允许这样做 有没有好的方法呢 您可以在表视图顶部添加图像视图或更改表视图的背景视图 Check i
  • 在两个可移动 uiview 之间画线

    我有一个带有节点的 滚动视图 UIViews 可以拖动 我正在尝试在选定的之间绘制边缘UIViews使用 calayer 但我不知道当视图位置发生变化时如何重新绘制线条 In my viewControllerI 类在节点数组中添加第一个和
  • Xcode 服务器 ibtool 构建失败

    我一直在研究使用 Xcode Server 进行 CI 我已经解决了一些问题 但现在有一个问题困扰着我 构建似乎工作正常 但在测试阶段挂起 并在日志底部生成以下内容 2015 11 25 14 44 45 650 xcodebuild 58
  • 如何使用固定宽度和自动布局正确缩放图像?

    我有一个动态 UIImage 和一个固定宽度为 280 0px 的 UIImageView 并且我正在使用自动布局 在 UIImage 视图上 我设置了宽度和高度约束 并降低了高度约束的优先级 我选择了 aspect fit 并将内容拥抱和
  • 如何在没有 MFMessageComposeViewController 的情况下发送和接收短信?

    我想发送和接收短信而不显示MFMessageViewController从我的申请中 有人能告诉我这怎么可能吗 不可能 除非您使用第 3 方 api 发送 接收短信

随机推荐

  • LINQ 使用 OR 连接

    我想使用 OR 语句与 LINQ 进行 JOIN 这是我开始的 SQL 查询 SELECT t id FROM Teams t INNER JOIN Games g ON g homeTeamId t id OR g awayTeamId
  • 如何跟踪 WinForms 中任何子控件何时获得或失去焦点?

    我有一个 Windows 窗体自定义控件 其作用类似于面板 因为它可以包含任意数量的子项 子控件的数量和类型是在运行时确定的 因此我需要以通用方式工作 而不知道可能存在或不存在的确切子控件 我想根据面板是否包含焦点来更改面板的背景颜色 因此
  • 在视图导出中获取摘要计数?

    我需要将视图导出到 Excel 我已经在某处找到了一些代码 它在 xpages 中运行得很好 现在用户想要添加总计摘要 我会解释 我有一个包含用户名 项目 ID 和设备 ID 的文档 我需要做的是导出具有特定项目 ID 的所有文档 在导出中
  • 如何在 C# 中更新查询字符串?

    网址中的某处有一个 sortBy 6 如何在单击按钮时将其更新为 sortBy 4 或 sortBy 2 我是否需要编写自定义字符串函数来创建正确的重定向 URL 如果我只需要附加一个查询字符串变量我会这样做 string complete
  • 使用此椭圆曲线点乘法计算的点不在曲线上,此类带来算术异常

    我得到了使用标准投影坐标进行点乘错误的堆栈 我不知道我错过了什么 但相乘的点并不位于曲线上 有时它会输出类似的内容算术异常 整数不可逆 public class ECPointArthimetic EllipticCurve ec priv
  • 在 redhat linux 上安装 docker - 'container-selinux' 和 'selinux-policy' 问题

    我在 EC2 上有 Linux 并尝试安装 Docker 如何解决 container selinux 和 selinux policy 的问题 lsb release d Description Red Hat Enterprise Li
  • 避免 R 中的 for 循环

    我想要一些关于编写更好的 R 代码的建议 我目前在 R 中编写了一个循环 但它存在性能问题 我无法集中精力对其进行矢量化 因为输出数据帧中的每一行都依赖于较早的行 并且它们会迭代地向下流动 因此我编写了一个循环来按顺序读 写行 我的代码示例
  • ruby-method_missing 返回无方法错误

    我正在尝试使用 method missing 将美元转换为不同的货币 class Numeric currency euro gt 2 yen gt 6 def method missing method id args block met
  • 类型错误:performanceMeasurement.startMeasurement 不是函数

    当尝试在 Next 13 中从 azure msal react 登录时 就发生了错误 当我检查错误日志时 它来自核心库 azure msal react 我也尝试过登录弹出窗口 但错误仍然相同 我有代码 在我的auth ts export
  • 使用 urllib2 进行 POST 调用而不是 GET

    关于 urllib2 和 POST 调用有很多东西 但我遇到了一个问题 我正在尝试对服务进行简单的 POST 调用 url http myserver post service data urllib urlencode name joe
  • 编译时错误和无法访问的代码

    好的 考虑下面的代码 private const int THRESHHOLD 2 static void Main string args string hello if THRESHHOLD gt 1 return Console Wr
  • ggplot更改网格以适应每月数据

    我有一个为期 1 年的数据集 名为afs20 其结构如下 datum包含数据点的日期 maand包含数据点的月份 delta包含目标变量 o ggplot afs20 o geom point aes x datum y delta sta
  • 使用 XPath 获取具有默认命名空间(无命名空间前缀)的元素

    在这个 SOAP XML 文件中 我怎样才能获得7关于使用 XPath 查询
  • Mono 编译器 // 终端模拟器问题

    当我尝试编译 csharp 或 fsharp 文件时出现此错误 使用 gnome 终端或 jetbrain rider 时会发生这种情况 它在 tty 或 xterm 和 urxvt 等终端中运行良好 我还能够编译 c c 和 go 代码
  • 提取服务器证书

    我需要帮助获取适当的代码片段来获取服务器证书 有效和无效 由 CA 签名和自签名 任何链接和参考都将受到高度赞赏 我有一个 UNIX 命令 它可以提供我想要的结果 但我想要使用 Java 得到相同的输出 UNIX 中的命令是这样的 echo
  • ItemTemplate 和 ItemContainerStyle 不能一起使用吗?

    我正在尝试将 ItemTemplate 和 ItemContainerStyle 应用于 ItemsControl
  • 更改 UIActionSheet 中项目的文本颜色 - iOS 8

    我一直在使用以下代码来更改我添加的项目的文本颜色UIActionSheet void willPresentActionSheet UIActionSheet actionSheet for UIView subview in action
  • 如何可移植地扩展使用 mmap() 访问的文件

    我们正在尝试改变 SQLite 一个嵌入式数据库系统 使用 mmap 而不是通常的 read 和 write 调用来访问 磁盘上的数据库文件 对整个数据使用单个大映射 文件 假设文件足够小 我们没有问题 在虚拟内存中为此寻找空间 到目前为止
  • Keras - 从一个神经网络做出两个预测

    我正在尝试组合由同一网络产生的两个输出 该网络对 4 类任务和 10 类任务进行预测 然后我希望将这些输出组合起来 得到一个长度为 14 的数组 我将其用作最终目标 虽然这似乎很有效 但预测总是针对一个类别 因此它会产生一个概率分布 该概率
  • 如何使用 NSVisualEffectView 制作平滑、圆润、类似体积的 OS X 窗口?

    I m currently trying to make a window that looks like the Volume OS X window 为了做到这一点 我有自己的NSWindow 使用自定义子类 它是透明的 无标题栏 无阴