[NSTextView selectedTextAttributes]
的默认值在我的应用中无法使用,因为我允许用户选择几乎与背景颜色完全相同的颜色(语法高亮显示)。
我已经写了一些数学来确定合适的颜色,可以用它来设置它:
textView.selectedTextAttributes = @{
NSBackgroundColorAttributeName: [NSColor yellowColor],
NSForegroundColorAttributeName: [NSColor redColor]
};
但是当窗口在后台时,它仍然使用系统默认的浅灰色。
我在活动与非活动窗口中附加了上述代码的屏幕截图。 - 如何更改非活动窗口的选定文本背景颜色?
答案 0 :(得分:10)
您可以通过覆盖NSLayoutManager
的绘图方法来覆盖颜色。
final class LayoutManager1: NSLayoutManager {
override func fillBackgroundRectArray(rectArray: UnsafePointer<NSRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: NSColor) {
let color1 = color == NSColor.secondarySelectedControlColor() ? NSColor.redColor() : color
color1.setFill()
super.fillBackgroundRectArray(rectArray, count: rectCount, forCharacterRange: charRange, color: color1)
color.setFill()
}
}
将NSTextView
的布局管理器替换为它。
textView.textContainer!.replaceLayoutManager(layoutManager1)
当@Kyle询问setFill
的原因时,我添加了一些更新。
来自Apple手册:
... charRange和颜色参数仅用于提供信息;颜色是 已设置为图形状态。如果由于任何原因您修改它,您必须先恢复它 从这个方法返回。 ...
这意味着将其他颜色传入super
调用无效,您只需要
NSColor.setFill
使其与super
电话合作。
此外,手册需要将其设置回原始版本。
答案 1 :(得分:5)
当窗口处于后台时,不是在未选择NSTextView时。我认为你不能改变这种行为。
您可以创建一个属性字符串,并在失去焦点时将NSBackgroundColorAttributeName属性添加到所选文本的范围内。即使焦点丢失,属性字符串也会保持相同的颜色。
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"hello world"];
[string addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(1, 7)];
[string addAttribute:NSBackgroundColorAttributeName value:[NSColor yellowColor] range:NSMakeRange(1, 7)];
[self.myTextView insertText:string];
编辑Abhi Beckert:这就是我实现这个答案的方法(注意我还必须禁用内置的选定文本属性,否则它们会覆盖我正在设置的那些):
@implementation MyTextView
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (!(self = [super initWithCoder:aDecoder]))
return nil;
// disable built in selected text attributes
self.selectedTextAttributes = @{};
return self;
}
- (id)initWithFrame:(NSRect)frameRect textContainer:(NSTextContainer *)container
{
if (!(self = [super initWithFrame:frameRect textContainer:container]))
return nil;
// disable built in selected text attributes
self.selectedTextAttributes = @{};
return self;
}
- (void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag
{
// remove from old ranges
for (NSValue *value in self.selectedRanges) {
if (value.rangeValue.length == 0)
continue;
[self.textStorage removeAttribute:NSBackgroundColorAttributeName range:value.rangeValue];
}
// apply to new ranges
for (NSValue *value in ranges) {
if (value.rangeValue.length == 0)
continue;
[self.textStorage addAttribute:NSBackgroundColorAttributeName value:[NSColor yellowColor] range:value.rangeValue];
}
[super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
}
@end
答案 2 :(得分:0)
您可以通过从layoutManagerOwnsFirstResponder(in:)覆盖NSLayoutManager来指定将NSTextView视为第一响应者,并且选择将使用您定义的属性。
在 Swift 5.1 中,将是:
override func layoutManagerOwnsFirstResponder(in window: NSWindow) -> Bool {
true
}