我知道这不是一个受欢迎的问题,有些人不喜欢具有非标准外观的应用,但它对我的应用非常有用。
是否可以以“标准”非私有API方式更改NSWindow标题栏文本的颜色?
我知道我可以使用私有API(as mentioned in this answer)但我认为可以在没有私有API的情况下进行,因为Pixelmator已经完成并且没有被MAS拒绝。我知道也可以这样做通过创建一个无边框窗口并自己绘制所有内容,但我不认为Pixelmator是如何做的,因为它们仍然可以获得标准NSWindow标题栏附带的所有附加位;可拖动图标,重命名窗口,下拉菜单文档修订和全屏按钮。
基本上,我使用setBackgroundColor创建了一个黑色窗口:但是文本仍然显示为黑色,但在黑色背景上不起作用。
那么有没有人知道这样做的方法,或者Pixelmator是如何做到的?
答案 0 :(得分:11)
从OS X 10.10开始,将窗口的外观更改为NSAppearanceNameVibrantDark
就足够了 window.appearance = NSAppearance(named:NSAppearanceNameVibrantDark)
认为值得一提,因为您可以找到的大部分答案都已过时。
答案 1 :(得分:2)
这是Swift的解决方案。已经很晚了,我累了,所以这可能不是最佳的,但它确实有效。
首先,这是一个在层次结构中查找视图的功能,可以选择跳过特定视图。 (如果我们要搜索window.contentView.superview.subviews
并且我们想在contentView
中忽略您自己的观点
func findViewInSubview(subviews: [NSView], #ignoreView: NSView, test: (NSView) -> Bool) -> NSView? {
for v in subviews {
if test(v) {
return v
} else if v != ignoreView {
if let found = findViewInSubview(v.subviews as [NSView], ignoreView: ignoreView, test) {
return found
}
}
}
return nil
}
以下是您将如何使用它,例如来自NSViewController
子类。请注意,您需要在窗口可见时执行此操作,因此您无法在viewDidLoad
中执行此操作。
override func viewDidAppear() {
if let windowContentView = view.window?.contentView as? NSView {
if let windowContentSuperView = windowContentView.superview {
let titleView = findViewInSubview(windowContentSuperView.subviews as [NSView], ignoreView: windowContentView) { (view) -> Bool in
// We find the title by looking for an NSTextField. You may
// want to make this test more strict and for example also
// check for the title string value to be sure.
return view is NSTextField
}
if let titleView = titleView as? NSTextField {
titleView.attributedStringValue = NSAttributedString(string: "Hello", attributes: [NSForegroundColorAttributeName: NSColor.redColor()])
}
}
}
}
请注意你正在玩火。像这样的内部结构是没有说明的原因。
答案 2 :(得分:0)
您可以使用某些私有API对问题的评论中提到的问题进行解决 - 但是,您无法将该应用提交到AppStore。
其他解决方案是获取[[myWindow contentView] superview]
- 它可以获得前面提到的NSThemeView
实例。您需要做的就是搜索NSTextField的任何实例的视图(实际上称为帧视图)子视图的子视图并修改它们。请注意,这些私有视图的层次结构可能随OS X的每个版本而变化,可能会破坏您的代码。
最好的解决方案是子类化(只有子类,没有其他自定义)NSWindow
并实现-title
和-setTitle:
方法 - 对于每个窗口,你要设置实际的标题到@""
(通过调用[super setTitle:@""]
),然后将您自己的,以编程方式创建的NSTextField
实例放入框架视图(即[[[self contentView] superview] addSubview:myTextField]
,其中myTextField
是文本字段。您需要弄清楚字段的确切位置等,但这是最简单的部分。