NSTableRowView/NSTableCellView how to set custom color to selected row?
first set tableview selection highlight style to
NSTableViewSelectionHighlightStyleNone
then in your tablView delegate implement
tableView:shouldSelectRow:
and write this code inside it:
NSTableViewRow *row= [_mainTable rowViewAtRow:selectedRow makeIfNecessary:NO];
row.backgroundColor = [your color];
return YES;
read these also https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSTableViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/NSTableViewDelegate/tableView:rowViewForRow:
for selection style https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSTableView_Class/index.html#//apple_ref/occ/instp/NSTableView/selectionHighlightStyle
This is to set the custom color to the selected row and also the highlighted text color. The output should look something like this,
In the above screenshot, we are doing
Setting the background selected color to white
Adding the corner radius
Changing the text color to blue
Adding the blue stroke color
You can do a lot more customization but this answer covers above-mentioned points.
1. Start with subclassing NSTableRowView
class CategoryTableRowView: NSTableRowView {
override func drawSelection(in dirtyRect: NSRect) {
if selectionHighlightStyle != .none {
let selectionRect = bounds.insetBy(dx: 2.5, dy: 2.5)
NSColor(calibratedRed: 61.0/255.0, green: 159.0/255.0, blue: 219.0/255.0, alpha: 1.0).setStroke()
NSColor(calibratedWhite: 1.0, alpha: 1.0).setFill()
let selectionPath = NSBezierPath(roundedRect: selectionRect, xRadius: 25, yRadius: 25)
selectionPath.fill()
selectionPath.stroke()
}
}
}
2. Return custom CategoryTableRowView() in the NSTableViewDelegate method
func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
return CategoryTableRowView()
}
3. Make sure you have selectionHighlightStyle
to regular in your ViewController class
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.selectionHighlightStyle = .regular
}
4. To set the textColor, create a subclass of NSTableCellView
class CategoryCellView: NSTableCellView {
@IBOutlet weak var categoryTextField: NSTextField!
override var backgroundStyle: NSView.BackgroundStyle {
willSet{
if newValue == .dark {
categoryTextField.textColor = NSColor(calibratedRed: 61.0/255.0, green: 159.0/255.0, blue: 219.0/255.0, alpha: 1.0)
} else {
categoryTextField.textColor = NSColor.black
}
}
}
}
override the backgroundStyle
property and set the desired color for the text.
Note: In my case, I have a custom cell which has a categoryTextField
outlet.So to set the text color I use:
categoryTextField.textColor = NSColor.black
5. Set custom class inside storyboard
I hope this helps. Thanks.
Solution
This should be done by subclassing NSTableRowView
and then returning your subclass in with the NSTableView
delegate method-(NSTableRowView*)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
Subclassing NSTableRowView
provides much more flexibility when modifying your row view. Returning your subclass in the NSTableView
delegate method above
will also automatically remove the background selection color when clicking from one row to the next (which is an open issue in the other answer provided).
Steps
First, subclass NSTableRowView
and override drawSelectionInRect
to change its background color when selected:
@implementation MyTableRowView
- (void)drawSelectionInRect:(NSRect)dirtyRect
{
[super drawSelectionInRect:dirtyRect];
[[NSColor yellowColor] setFill];
NSRectFill(dirtyRect);
}
Next, return your subclassed row view using the rowViewForRow
NSTableView
delegate method:
- (NSTableRowView*)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
{
static NSString* const kRowIdentifier = @"MyTableRow";
MyTableRowView* myRowView = [tableView makeViewWithIdentifier:kRowIdentifier owner:self];
if (!myRowView) {
myRowView = [[MyTableRowView alloc] initWithFrame:NSZeroRect];
myRowView.identifier = kRowIdentifier;
}
return rowView;
}
Using this approach, you can also easily override other elements like the separator color. To do this, override the drawSeparatorInRect
method in your NSTableRowView
subclass like so:
- (void)drawSeparatorInRect:(NSRect)dirtyRect
{
// Change the separator color if the row is selected
if (self.isSelected) [[NSColor orangeColor] setFill];
else [[NSColor grayColor] setFill];
// Fill the seperator
dirtyRect.origin.y = dirtyRect.size.height - 1.0;
dirtyRect.size.height = 1.0;
NSRectFill(dirtyRect);
}
Resources
Overriding NSTableRowView
display settings
https://developer.apple.com/reference/appkit/nstablerowview
NSTableview rowViewForRow
delegate method
https://developer.apple.com/reference/appkit/nstableviewdelegate/1532417-tableview