6

我正在尝试将 iOS 应用程序移植到 Mac 上,但在过渡期间遇到了一些问题。其中之一是NSTableView. 和 custom basedNSCell之间到底有什么区别?我最初是从基于视图的 开始的,但我很快注意到我必须自己处理选择。我无法做到这一点,所以我继续使用,奇怪的是,它不会调用我的 custom 的初始化程序。NSTableRowViewNSViewNSTableviewNSTableViewNSTableRowViewNSTableRowView

我基本上只想要一个带有自定义内容的自定义表格视图单元格,它是可选的。最好的方法是什么?

在 iOS 上,我只是子类化UITableViewCell并设置它的 selectedView 属性。在 Mac 上,这似乎比这更复杂。

4

4 回答 4

18

实际上,我刚刚(在侧边栏中)发现了这个问题,它建议 subclass NSTableRowView。我之前已经这样做了,但是没有用。我再次尝试了它,令人惊讶的是它现在可以工作了......

在基于视图的 NSTableView 中处理自定义选择样式

但是,这个答案的信息量不是很大,所以我将尝试介绍我为完成这项工作所做的工作。

首先,我实现了下面的 NSTableView 委托方法并返回 nil!

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{

    return nil;

}

为了使用基于视图(我猜 NSTableViewRow 也被视为基于视图的表......)表,您必须实现此方法。我不太确定我可能做错了什么,但是如果没有这种方法,我的单元格将不会显示!

确保不要让 NSTableView 通过设置此属性来处理任何选择:

yourNSTableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleNone;

好的,现在我们要使用以下委托方法设置我们的单元格:

-(NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row{

    static NSString *cellID = @"cell_identifier";

    //use this if you want to reuse the cells
    CustomTableRowView *result = [tableView makeViewWithIdentifier:cellID owner:self];

    if (result == nil) {

        result = [[CustomTableRowView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, 80)];
        result.identifier = cellID;

    }

    result.data = [tableData objectAtIndex:row];

    // Return the result
    return result;

}

好的,现在子类NSTableRowView化并实现/覆盖以下两种方法:

首先,我们必须覆盖setSelected:以使单元格在被选中时重绘其背景。所以这里是:

-(void)setSelected:(BOOL)selected{

    [super setSelected:selected];
    [self setNeedsDisplay:YES];

}

如前所述,我们调用setNeedsDisplay:是为了让单元格重绘其背景。

最后是绘图代码。覆盖这样的方法drawBackgroundInRect:

-(void)drawBackgroundInRect:(NSRect)dirtyRect{
    if (!self.selected) {
        [[NSColor clearColor] set];
    } else {
        [someColor set];
    }
    NSRectFill(dirtyRect);
}
于 2014-01-17T16:57:32.803 回答
4

使用以下代码响应 NSTableViewDelegate 协议 tableViewSelectionDidChange:

获取所选行的 NSTableRowView 并对其调用 setEmphasized 方法。当 setEmphasized 设置为 YES 时,您将获得蓝色突出显示,当您设置为 NO 时,您将获得灰色突出显示。

-(void)tableViewSelectionDidChange:(NSNotification *)aNotification {

     NSInteger selectedRow = [myTableView selectedRow];
     NSTableRowView *myRowView = [myTableView rowViewAtRow:selectedRow makeIfNecessary:NO];
    [myRowView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleRegular];
     [myRowView setEmphasized:NO];
}

并避免蓝色然后灰色设置的跳舞效果

[_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];
于 2014-12-04T07:50:49.527 回答
2

the_critic 在 Swift 中的解决方案:(使用 XCode 7 beta3、Swift 2.0 测试)

class CustomTableRowView: NSTableRowView {

    override var selected: Bool {
        willSet(newValue) {
            super.selected = newValue;
            needsDisplay = true
        }
    }

    override func drawBackgroundInRect(dirtyRect: NSRect) {
        let context: CGContextRef = NSGraphicsContext.currentContext()!.CGContext

        if !self.selected {
            CGContextSetFillColorWithColor(context, NSColor.clearColor().CGColor)
        } else {
            CGContextSetFillColorWithColor(context, NSColor.redColor().CGColor)
        }

        CGContextFillRect(context, dirtyRect)
    }

}

视图控制器:

class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

    // [...]

    func tableView(tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
        guard let rowView = tableView.makeViewWithIdentifier("RowView", owner: nil) as! CustomTableRowView? else {
            let rowView = CustomTableRowView()
            rowView.identifier = "RowView"
            return rowView
        }

        return rowView
    }

}
于 2015-07-21T06:46:52.127 回答
0

毕竟,您可以在 IB 中设置它,它是设置“突出显示”,在“样式”下,在“交替行”复选框上方。设置为“无”,等等:

在此处输入图像描述

于 2021-01-22T21:46:59.160 回答