如何在基于视图的 NSOutlineView 中自定义 groupItem-look?

Posted

技术标签:

【中文标题】如何在基于视图的 NSOutlineView 中自定义 groupItem-look?【英文标题】:How do you customise the groupItem-look in a view-based NSOutlineView? 【发布时间】:2015-04-27 07:23:45 【问题描述】:

如何在基于视图的 NSOutlineView 中自定义 groupItem 外观?我想摆脱分隔线边框,更改背景颜色并使显示三角形变暗。显示三角形的背景应与 groupItem-view 背景颜色相同。

我无法通过全能的 Google 找到任何相关信息。

【问题讨论】:

【参考方案1】:

View Based NSOutlineView 使用以下 NSOutlineView*Keys 来创建用于折叠和展开项目的“披露按钮”。

APPKIT_EXTERN NSString * const NSOutlineViewDisclosureButtonKey NS_AVAILABLE_MAC(10_9); // The normal triangle disclosure button
APPKIT_EXTERN NSString * const NSOutlineViewShowHideButtonKey NS_AVAILABLE_MAC(10_9); // The show/hide button used in "Source Lists"

NSOutlineView 通过调用[self makeViewWithIdentifier:owner:] 来创建这些按钮,将键作为标识符传递,委托作为所有者。可以为 NSOutlineView 提供自定义 NSButton(或其子类),以通过以下两种方式使用:

    makeViewWithIdentifier:owner: 可以被覆盖,如果标识符是(例如)NSOutlineViewDisclosureButtonKey,则可以配置并返回自定义的 NSButton。请务必将 button.identifier 设置为 NSOutlineViewDisclosureButtonKey。

    在设计时,可以将一个按钮添加到具有此标识符的大纲视图中,并将取消存档并根据需要使用。

    当使用自定义按钮时,正确设置目标/动作以执行某些操作(可能展开或折叠发送者所在的 rowForView:)非常重要。或者,可以调用 super 来获取默认按钮,并复制其目标/动作以获取正常的默认行为。

    注意:这些键向后兼容 10.7,但是,符号不会在 10.9 之前导出,并且必须使用常规字符串值(即:@"NSOutlineViewDisclosureButtonKey")。

如果你还想改变位置,那么继承你的 NSTableRowView 并覆盖布局方法

- (void)layout 

    [super layout];

    for (NSView * v in self.subviews) 
        if ([v.identifier isEqual:NSOutlineViewDisclosureButtonKey]) 
            v.frame = NSMakeRect(self.bounds.size.width - 44, 0, 44, self.bounds.size.height);
            v.hidden = NO;
            break;
        
    


以及被覆盖的 NSOutlineView 的代码

- (NSView *)makeViewWithIdentifier:(NSString *)identifier owner:(id)owner 

    NSView * v = [super makeViewWithIdentifier:identifier owner:owner];

    if ([identifier isEqual:NSOutlineViewDisclosureButtonKey] && ([v isKindOfClass:[NSButton class]])) 

        MenuDisclosureButton * b = [[MenuDisclosureButton alloc] initWithFrame:NSMakeRect(0, 0, 44, 44)];
        b.target = [(NSButton *)v target];
        b.action = [(NSButton *)v action];
        b.identifier = NSOutlineViewDisclosureButtonKey;
        v = b;

    

    return v;

【讨论】:

这很好,但只涵盖了披露按钮 - 不是实际的组行外观。我找不到可以子类化/替换 NSTableRowView 的位置(在 NSOutlineView 的 .xib 层次结构和标题中都没有找到它)。甚至无法理解它在剧中的作用,转播到我可以并且可以自定义的 NSTableCellView。您能否进一步说明这一点,或者至少直接参考解释其工作原理的文档?【参考方案2】:

要自定义(或隐藏)三角形按钮,只需覆盖 NSOutlineView 类。兴趣方式为- (id)makeViewWithIdentifier:(NSString *)identifier owner:(id)owner

// your NSOutlineView child class

- (id)makeViewWithIdentifier:(NSString *)identifier owner:(id)owner

   id view = [super makeViewWithIdentifier:identifier owner:owner];
   if ([identifier isEqualToString:@"NSOutlineViewDisclosureButtonKey"])
     
      NSButton *triangleButton = (NSButton *)view;
      NSImage *image = [[NSImage alloc] init]; // you could set another images
      [triangleButton setImage:image];
      [triangleButton setAlternateImage:image];
     
   return view;

从现在起必须隐藏三角形按钮。但是您的可扩展项目仍然存在缩进问题。

打开 Interface Builder 并选择您的大纲视图实例。打开属性检查器,将 Indentation 属性设置为零。

更新

在组项目视图中,三角形后面有一个空白区域。就像我上面所说的,只是为了删除它,将缩进属性设置为零。

要设置自定义分隔符,只需删除 NSOutlineView 的分隔符并自己绘制(在“单元”类的 drawRect 方法中),如果要自定义显示按钮,请在 NSView-“单元”中实现自己的子类。

【讨论】:

但我确实想在大纲视图中使用缩进。边框和背景颜色呢? @SeppoSilaste 创建自定义 NSView 子类,设置背景和边框(通过drawRect),将其用于基于视图的大纲视图。 如果我将缩进设置为 0,则显示三角形不会显示,因为它没有空间。您是否建议我将讨论按钮移动到我的“单元格”视图并自己实现其功能? 那么披露按钮呢:您是否将自己的按钮添加到“组项目单元格”? @Melodius 是的,我愿意。并实现自定义操作选择器。

以上是关于如何在基于视图的 NSOutlineView 中自定义 groupItem-look?的主要内容,如果未能解决你的问题,请参考以下文章

NSTreeController/NSOutlineView 失去选择

如何遍历我的 NSOutlineView 的所有项目?

从 NSOutlineView 中拖放

SwiftUI:如何从 OutlineGroup 中获取选择?

NSTableView 和 NSOutlineView 在 tab 键上编辑

如何在 Qt 中自定义列表视图