8

NSOutlineView是 的子类NSTableView。目前,NSTableView支持两种实现。

  • 基于细胞。
  • 基于视图。

要制作 OSX 10.8 Finder 样式的侧边栏(带有自动灰色图标样式),需要使用具有源列表突出显示样式的基于视图的表格视图。

对于 NIB,这是典型的工作。没什么难的。(参见SidebarDemo)但我想避免使用任何 NIB 或 Interface Builder。我想纯粹以编程方式制作侧边栏。

在这种情况下,我有很大的问题。AFAIK,无法为特定单元格提供原型视图。当我打开.xib文件时,我看到<tableColumn>包含<prototypeCellViews>. 这指定了该列将使用什么视图。我找不到如何使用公共 API 以编程方式设置它。

作为一种解决方法,我尝试使用-[NSTableView makeViewWithIdentifier:owner:]and手动制作单元格-[NSTableView viewAtColumn:row:makeIfNecessary:],但它们都没有返回视图实例。我创建了一个NSTableCellView,但它没有图像视图和文本字段实例。而且我也尝试设置它们,但是这些字段被标记为assign立即释放实例。我试图通过强制保留它们来保留它,但它不起作用。NSTableView不管理它们,所以我确信表格视图不喜欢我的实现。

我相信有一个属性可以为列设置此原型视图。但我找不到他们。我在哪里可以找到该属性并以NSOutlineView编程方式使用源列表样式设置系统默认值?

4

3 回答 3

5

如果您遵循 中的示例SidebarDemo,它们将使用 的子类NSTableCellView作为详细信息行。为了模拟InterfaceBuilder mojo,您可以在构造函数中将所有内容挂钩。其余部分与演示相同(请参阅 参考资料outlineView:viewForTableColumn:item:)。

@interface SCTableCellView : NSTableCellView
@end

@implementation SCTableCellView

- (id)initWithFrame:(NSRect)frameRect {
  self = [super initWithFrame:frameRect];
  [self setAutoresizingMask:NSViewWidthSizable];
  NSImageView* iv = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 6, 16, 16)];
  NSTextField* tf = [[NSTextField alloc] initWithFrame:NSMakeRect(21, 6, 200, 14)];
  NSButton* btn = [[NSButton alloc] initWithFrame:NSMakeRect(0, 3, 16, 16)];
  [iv setImageScaling:NSImageScaleProportionallyUpOrDown];
  [iv setImageAlignment:NSImageAlignCenter];
  [tf setBordered:NO];
  [tf setDrawsBackground:NO];
  [[btn cell] setControlSize:NSSmallControlSize];
  [[btn cell] setBezelStyle:NSInlineBezelStyle];
  [[btn cell] setButtonType:NSMomentaryPushInButton];
  [[btn cell] setFont:[NSFont boldSystemFontOfSize:10]];
  [[btn cell] setAlignment:NSCenterTextAlignment];
  [self setImageView:iv];
  [self setTextField:tf];
  [self addSubview:iv];
  [self addSubview:tf];
  [self addSubview:btn];
  return self;
}

- (NSButton*)button {
  return [[self subviews] objectAtIndex:2];
}

- (void)viewWillDraw {
  [super viewWillDraw];
  NSButton* btn = [self button];
  ...
于 2013-11-26T01:51:00.490 回答
5

这是@jeberle 用 Swift 4 重写的代码(五年后!):

class ProgrammaticTableCellView: NSTableCellView {
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)

        self.autoresizingMask = .width
        let iv: NSImageView = NSImageView(frame: NSMakeRect(0, 6, 16, 16))
        let tf: NSTextField = NSTextField(frame: NSMakeRect(21, 6, 200, 14))
        let btn: NSButton = NSButton(frame: NSMakeRect(0, 3, 16, 16))
        iv.imageScaling = .scaleProportionallyUpOrDown
        iv.imageAlignment = .alignCenter
        tf.isBordered = false
        tf.drawsBackground = false
        btn.cell?.controlSize = .small
        // btn.bezelStyle = .inline                  // Deprecated?
        btn.cell?.isBezeled = true                   // Closest property I can find.
        // btn.cell?.setButtonType(.momentaryPushIn) // Deprecated?
        btn.setButtonType(.momentaryPushIn)
        btn.cell?.font = NSFont.boldSystemFont(ofSize: 10)
        btn.cell?.alignment = .center

        self.imageView = iv
        self.textField = tf
        self.addSubview(iv)
        self.addSubview(tf)
        self.addSubview(btn)
    }

    required init?(coder decoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    var button: NSButton {
        get {
            return self.subviews[2] as! NSButton
        }
    }
}

编辑:我找到了一个指向 Apple 的SidebarDemo的链接(这将不可避免地消失——它最后一次修订是在 2011 年), @ jeberle 是基于他的代码。

于 2018-08-07T22:52:42.750 回答
4

除了@jeberle 的回答,我还需要注意一些事情。

  • 保留文本字段和图像视图的关键是将它们添加为NSTableCellView.

  • 设置NSTableView.rowSizeStyle为适当的值(非Custom默认值)以使表格视图自动布局它们。否则,您必须自己完全布局它们。

  • 如果您想使用预定义的值,请不要触摸frame和填充。否则,布局可能会被破坏。autoresizingNSTableViewRowSizeStyle

  • private func outlineView(outlineView: NSOutlineView, heightOfRowByItem item: AnyObject) -> CGFloat您可以通过提供委托方法来调整行高。设置NSTableView.rowHeight不是一个好主意,因为它需要NSTableView.rowSizeStyle设置为Custom默认关闭单元格文本/图像布局管理。

  • NSView.identifier您可以通过设置属性重用行/单元格视图。(示例

于 2014-10-12T13:38:57.350 回答