View-based NSTableView selection?

147 views Asked by At

I wrote a view-based tableview, like this: enter image description here

and I draw selection with NSTableRowView, code is like this:

- (void)drawRect:(NSRect)dirtyRect {
  [[NSColor clearColor] setFill];
  if (self.isClicked) {
    [[[NSColor blackColor] colorWithAlphaComponent:0.08] setFill];
  }
  NSRect rowViewRect = NSMakeRect(0, 0, 274, 72);
  NSBezierPath *path = [NSBezierPath bezierPathWithRect:rowViewRect];
  [path fill];
}

But finally, I found the TableRowView is not over the tableView, so the selectedColor not cover the image and the button, it more like background color, but I need the selected TableRowView cover the view, just like this:

enter image description here

The selected color cover the image and the button. I have googled, but not found any ideas. Thanks for help~

1

There are 1 answers

3
rocky On BEST ANSWER

So this is a bit tricky. The strategy is to have an overlay colored view with alpha less than 1 in your NSTableCellView and then add and remove it based on the cell's selection.

First, you need an NSView that can set a background color:

NSView_Background.h

@interface NSView_Background : NSView 
@property (nonatomic, strong) NSColor *background;
@end

NSView_Background.m

#import "NSView_Background.h"

@implementation NSView_Background

- (void)drawRect:(NSRect)dirtyRect {
    [self.background set];
    NSRectFill([self bounds]);
}

- (void)setBackground:(NSColor *)color {
    if ([_background isEqual:color]) return;

    _background = color;

    [self setNeedsDisplay:YES];
}
@end

Second, in your NSTableCellView subclass, add a NSView_Background property:

#import "NSView_Background.h"

@interface
@property (nonatomic, strong) NSView_Background *selectionView;
@end

Third, add this method to NSTableCellView subclass:

- (void)shouldShowSelectionView:(BOOL)shouldShowSelectionView {
    if (shouldShowSelectionView) {
        self.selectionView = [[NSView_Background alloc] init];
        [self.selectionView setBackground:[NSColor grayColor]];
        self.selectionView.alpha = 0.4;
        [self addSubview:self.selectionView];

        [self setNeedsDisplay:YES];   // draws the selection view
    } else {
        [self.selectionView removeFromSuperview];
        self.selectionView = nil;
    }
}

Fourth, add this to drawRect in your NSTableCellView subclass:

- (void)drawRect:(NSRect)dirtyRect {
    if (self.selectionView)
        self.selectionView.frame = self.bounds;
}

Finally, override NSTableCellView:setBackgroundStyle:

- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
    switch (backgroundStyle) {
        case: NSBackgroundStyleDark:
            [self shouldShowSelectionView:YES];
            break;
        default:
            [self shouldShowSelectionView:NO];
            break;
    }
}

I know this seems hacky but this is the only way I could get this behavior. Hope this helps and good luck!