Change selection color on view-based NSTableView

风格不统一 提交于 2019-11-27 10:07:46

问题


Standard highlighting color in OS X applications is blue.

Is it possible to change it to another color, e.g. gray?

Note that I am using the new view-based NSTableView available starting from OS X 10.7.


回答1:


Since you're using the view based NSTableView, you can subclass NSTableRowView, feed it to the table delegate method - (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row;, then customize your selection in the row view class.

Here's an example:

- (void)drawSelectionInRect:(NSRect)dirtyRect {
    if (self.selectionHighlightStyle != NSTableViewSelectionHighlightStyleNone) {
        NSRect selectionRect = NSInsetRect(self.bounds, 2.5, 2.5);
        [[NSColor colorWithCalibratedWhite:.65 alpha:1.0] setStroke];
        [[NSColor colorWithCalibratedWhite:.82 alpha:1.0] setFill];
        NSBezierPath *selectionPath = [NSBezierPath bezierPathWithRoundedRect:selectionRect xRadius:6 yRadius:6];
        [selectionPath fill];
        [selectionPath stroke];
    }
}



回答2:


Here is James Chen's solution in Swift 3. I've also added the delegate method.

class MyNSTableRowView: NSTableRowView {

    override func drawSelection(in dirtyRect: NSRect) {
        if self.selectionHighlightStyle != .none {
            let selectionRect = NSInsetRect(self.bounds, 2.5, 2.5)
            NSColor(calibratedWhite: 0.65, alpha: 1).setStroke()
            NSColor(calibratedWhite: 0.82, alpha: 1).setFill()
            let selectionPath = NSBezierPath.init(roundedRect: selectionRect, xRadius: 6, yRadius: 6)
            selectionPath.fill()
            selectionPath.stroke()
        }
    }
}

NSTableViewDelegate:

func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
    return MyNSTableRowView()
}



回答3:


Use the following code in response to the NSTableViewDelegate protocol tableViewSelectionDidChange:

Get the NSTableRowView for the selected row and call the method setEmphasized on it. When setEmphasized is set to YES you get the blue highlight, when NO you get the gray highlight.

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

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



回答4:


Some modifications to Jean-Pierre answer

Use the following code in response to the NSTableViewDelegate protocol tableViewSelectionDidChange:

Get the NSTableRowView for the selected row and call the method setEmphasized on it. When setEmphasized is set to YES you get the blue highlight, when NO you get the gray highlight.

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

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

And to avoid dancing effect of blue then gray set

[_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];



回答5:


I've mixed all methods described before and got code that exactly do what I want.

  • Selection not change color of textfields inside;
  • Rows remember selection and color of one;
  • Any strange outer borders and other leftovers appear.

    class AudioCellView: NSTableRowView {
    
        override func draw(_ dirtyRect: NSRect) {
            super.draw(dirtyRect)
            self.wantsLayer = true
            self.layer?.backgroundColor = NSColor.white.cgColor
        }
    
        override var isEmphasized: Bool {
            set {}
            get {
                return false
            }
        }
    
        override var selectionHighlightStyle: NSTableView.SelectionHighlightStyle {
            set {}
            get {
                return .regular
            }
        }
    
        override func drawSelection(in dirtyRect: NSRect) {
            if self.selectionHighlightStyle != .none {
                let selectionRect = NSInsetRect(self.bounds, 2.5, 2.5)
                NSColor(calibratedWhite: 0.85, alpha: 0.6).setFill()
                let selectionPath = NSBezierPath.init(rect: selectionRect)
                selectionPath.fill()
            }
        }
    }
    



回答6:


When using Swift you can do this on 10.10 for view based Cells

Subclass the NSTableCellView and implement this:

//override to change background color on highlight
override var backgroundStyle:NSBackgroundStyle{
    //check value when the style was setted
    didSet{
        //if it is dark the cell is highlighted -> apply the app color to it
        if backgroundStyle == .Dark{
            self.layer!.backgroundColor = yourColor
        }
        //else go back to the standard color
        else{
            self.layer!.backgroundColor = NSColor.clearColor().CGColor
        }
    }
}

Note that the NSTableView highlight style must be set to Regular if it is on SourceList it will cause some strange clipping.

This is not the cleanest solution but it works good on yosemite




回答7:


As already mentioned, set emphasized attribute to false, but do it in the custom NSTableRowView class to avoid side effects (like dancing color effect):

    override func drawRect(dirtyRect: NSRect) {
       super.drawRect(dirtyRect)
       self.emphasized = false

    }



回答8:


It seems to me there is an option available to change this coz the documentation says three selection style and the default style in regular is blue, look at the image below.. you need to send it a message which I cant figure out as I have never developed apps for mac before.. hoping this helps...!




回答9:


You have to subclass NSTableView, and rewrite the functions below in order to change the alternating colors.

  • (void) drawRow: (NSInteger) row clipRect: (NSRect) clipRect

  • (void) drawBackgroundInClipRect: (NSRect) clipRect ** This one to change the main and alternate color **

Use a for loop and insert this conditional (i % 2 == 0) to detect odd and even rows.




回答10:


Okay, So I do know that it already has an accepted answer, but for anyone like me working with an NSOutlineView and has .selectionHighlightStyle = .sourceList can use this code to make the selection grey. This method will not flicker when changing the selection and will also stay grey if the app is minimised.

NSTableView/NSOutlineView Delegate:

func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView?
{
     let row : CustomRowView = CustomRowView.init()
     row.identifier = "row"

     return row
}

And then create a new CustomRowView.swift file with this:

class CustomRowView : NSTableRowView
{
    override var isEmphasized: Bool {
        get { return self.isEmphasized }
        set(isEmp) { self.isEmphasized = false }
    }
}

This will keep the selection grey at all times.




回答11:


This is Jean-Pierre's answer in Swift3:

func tableViewSelectionDidChange(_ notification: Notification)
    { 
        index = tableView.selectedRow
        let rowView = tableView.rowView(atRow: index, makeIfNecessary: false)
        rowView?.isEmphasized = false
...

It has the two limitations listed above -- first click doesn't work, second click does. And, there is a "dancing effect". I don't mind the first and actually like the second.




回答12:


- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    [tblCategory enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row){
        CustomMainCell *cellView = [rowView viewAtColumn:0];
        if(rowView.selected){
            cellView.txtFieldTitle.textColor=[NSColor colorWithCalibratedRed:245.0/255.0 green:110.0/255.0 blue:65.0/255.0 alpha:1.0];
        }else{
            cellView.txtFieldTitle.textColor=[NSColor whiteColor];
        }
    }];
}

[tblCategory setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];




回答13:


  Use this Notification for NSTableView:

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

                 //You Logic stuff
             }


来源:https://stackoverflow.com/questions/9463871/change-selection-color-on-view-based-nstableview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!