基于视图的“源列表”NSOutlineView的自定义选择样式

时间:2014-11-12 09:57:23

标签: objective-c macos cocoa nsoutlineview appkit

我正在使用基于NSOutlineView的视图,其selectionHighlightStyle设置为NSTableViewSelectionHighlightStyleSourceList

我想覆盖某些行的选择样式(背景)并绘制不同的颜色/渐变。

到目前为止,我尝试创建自定义NSTableRowView并通过outlineView:rowViewForItem:返回。 我验证了我的自定义行视图是由大纲视图委托创建并返回的。 但是,我没有调用我在自定义行视图中覆盖的方法。

我尝试覆盖drawBackgroundInRect:drawSelectionInRect:drawSeparatorInRect:甚至drawRect:。这些都没有被称为。

我怀疑大纲视图在设置为源列表样式时会做一些自定义的“魔术”,但是我没有在文档中找到任何表明自定义NSTableRowView不会的内容在这种情况下,我将受到尊重。

3 个答案:

答案 0 :(得分:3)

使用NSVisualEffectView时,AppKit会将自定义素材的单独NSTableViewSelectionHighlightStyleSourceList添加到行视图以绘制背景。我提出了以下使用零私有API的解决方法,但如果Apple实现了一些突出显示行的其他方法,可能会稍后破解。

@class CustomHighlightRowSelectionView;
@interface CustomHighlightRowView : NSTableRowView

@property (nonatomic, strong) CustomHighlightRowSelectionView *selectionView;

@end

@interface CustomHighlightRowSelectionView : NSView

@property (nonatomic, getter=isEmphasized) BOOL emphasized;
@property (nonatomic, getter=isSelected) BOOL selected;

@end


@implementation CustomHighlightRowView

- (CustomHighlightRowSelectionView *)selectionView
{
    if (!_selectionView)
    {
        _selectionView = [[CustomHighlightRowSelectionView alloc] initWithFrame:NSZeroRect];
    }

    return _selectionView;
}

- (void)setEmphasized:(BOOL)emphasized
{
    [super setEmphasized:emphasized];
    self.selectionView.emphasized = emphasized;
}

- (void)setSelected:(BOOL)selected
{
    [super setSelected:selected];
    self.selectionView.selected = selected;
}

- (void)addSubview:(NSView *)aView positioned:(NSWindowOrderingMode)place relativeTo:(NSView *)otherView
{
    if (![aView isKindOfClass:[NSVisualEffectView class]])
    {
        [super addSubview:aView positioned:place relativeTo:otherView];
    }
    else
    {
        if (!self.selectionView.superview)
        {
            [super addSubview:self.selectionView positioned:place relativeTo:otherView];
            self.selectionView.frame = self.bounds;
        }
    }
}

- (void)setFrame:(NSRect)frame
{
    [super setFrame:frame];

    self.selectionView.frame = self.bounds;
}

- (void)setBounds:(NSRect)bounds
{
    [super setBounds:bounds];

    self.selectionView.frame = self.bounds;
}

@end

@implementation CustomHighlightRowSelectionView

- (void)setEmphasized:(BOOL)emphasized
{
    _emphasized = emphasized;
    [self setNeedsDisplay:YES];
}

- (void)setSelected:(BOOL)selected
{
    _selected = selected;
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)dirtyRect
{
    if (!self.selected)
    {
        return;
    }

    NSColor *fillColor = self.emphasized ? [NSColor alternateSelectedControlColor] : [NSColor secondarySelectedControlColor];
    [fillColor setFill];
    NSRectFill(dirtyRect);
}

@end

答案 1 :(得分:1)

你正在使用约塞米蒂吗? 来自Apple的文档Adopting Advanced Features of the new UI in Yosemite

  

当selectionHighlightStyle ==时   NSTableViewSelectionHighlightStyleSourceList•选择现在是   窗口混合后面的特殊蓝色材料    - 无法自定义材料尺寸和图纸

如果你将它设置为NSTableViewSelectionHighlightStyleRegular并覆盖drawRect,它应该可以工作。

答案 2 :(得分:0)

您需要在NSTableRowView子类中覆盖-selectionHighlightStyle:

- (NSTableViewSelectionHighlightStyle)selectionHighlightStyle
{
    return NSTableViewSelectionHighlightStyleRegular;
}

这样,表视图可以在源列表样式中使用,但具有自定义行选择。我希望在我的项目中使用Yosemite下的源列表,但是使用系统偏好设置中用户选择的颜色。

编辑:我只是注意到这样做会导致单元格视图中的文本字段和图像视图出现像边框看起来非常奇怪和丑陋的神器。