基于视图的NSTableView选择突出显示

时间:2014-01-17 16:51:49

标签: objective-c macos nstableview nstableviewcell

我正在尝试将iOS应用程序移植到Mac上,并且在转换过程中遇到了一些问题。其中之一是NSTableView的自定义。基于NSCell的{​​{1}},NSTableRowView和自定义NSView之间究竟有什么区别?我最初开始使用基于NSTableview的视图,但我很快就注意到我必须自己处理选择。我无法取消它,所以我继续使用NSTableView,奇怪的是,它不会调用我的自定义NSTableRowView的初始化程序。

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

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

4 个答案:

答案 0 :(得分:18)

我实际上刚刚找到(在侧边栏中)这个问题,建议继承NSTableRowView。我之前已经这样做了,但它没有用。我再次尝试过,而且很令人惊讶它现在有效......

  

Handling custom selection style in view based 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);
}

答案 1 :(得分:3)

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

获取所选行的NSTableRowView并在其上调用setEmphasized方法。当setEmphasized设置为YES时,您将获得蓝色突出显示,如果不是,则获得灰色突出显示。

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

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

为了避免蓝色的跳舞效果,然后灰色设置

[_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];

答案 2 :(得分: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)
    }

}

的ViewController:

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
    }

}

答案 3 :(得分:0)

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

enter image description here