Change NSTableView alternate row colors

前端 未结 9 1207

I\'m using the \"Alternating Rows\" option in Interface Builder to get alternating row colors on an NSTableView. Is there any way to change the colors of the alternating row

相关标签:
9条回答
  • 2020-12-28 17:38

    I subclassed NSTableView and implemented drawRow:clipRect: like this...

    - (void)drawRow:(NSInteger)row clipRect:(NSRect)clipRect
    {
        NSColor *color = (row % 2) ? [NSColor redColor] : [NSColor whiteColor];
        [color setFill];
        NSRectFill([self rectOfRow:row]);
        [super drawRow:row clipRect:clipRect];
    }
    

    It seems to work, but it's so simple that I'm wondering if I'm missing something.

    0 讨论(0)
  • 2020-12-28 17:40

    If you want to use an undocumented way, make a NSColor category and override _blueAlternatingRowColor like this:

    @implementation NSColor (ColorChangingFun)
    
    +(NSColor*)_blueAlternatingRowColor
    {
        return [NSColor redColor];
    }
    
    @end
    

    or to change both colors, override controlAlternatingRowBackgroundColors to return an array of colors you want alternated.

    @implementation NSColor (ColorChangingFun)
    
    +(NSArray*)controlAlternatingRowBackgroundColors
    {
        return [NSArray arrayWithObjects:[NSColor redColor], [NSColor greenColor], nil];
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-28 17:41

    I'm not sure how recently this was added, or if it is as flexible as you need it to be, but I noticed that you can specify "Alternating" rows in Interface Builder in Xcode 4.6 (and possibly earlier).

    1. Open your nib in Xcode and select your NSTableView or NSOutlineView
    2. Show the Attributes Inspector in the Utilities Pane (⎇⌘4)
    3. Notice the Highlight Alternating Rows checkbox.

    enter image description here

    0 讨论(0)
  • 2020-12-28 17:44

    There is no settable property for this, however you can respond to the delegate method -tableView:willDisplayCell:forTableColumn:row: and set the cell's background color based on the evenness of the row number.

    0 讨论(0)
  • 2020-12-28 17:46

    Swift 4+ version of AlternateRealist's answer:

    public class AlternateBgColorTableView: NSTableView {
        var alternateBackgroundColor: NSColor? = .red
    
        override public func drawBackground(inClipRect clipRect: NSRect) {
            // If we didn't set the alternate color, fall back to the default behavior
            guard let alternateBackgroundColor = alternateBackgroundColor else {
                super.drawBackground(inClipRect: clipRect)
    
                return
            }
    
            // Fill in the background color
            backgroundColor.set()
            clipRect.fill()
    
            // Check if we should be drawing alternating colored rows
            if usesAlternatingRowBackgroundColors {
                // Set the alternating background color
                alternateBackgroundColor.set()
    
                // Go through all of the intersected rows and draw their rects
                var checkRect = bounds
                checkRect.origin.y = clipRect.origin.y
                checkRect.size.height = clipRect.height
                let rowsToDraw = rows(in: checkRect)
                var currentRow = rowsToDraw.location
    
                repeat {
                    if currentRow % 2 != 0 {
                        // This is an alternate row
                        var rowRect = rect(ofRow: currentRow)
                        rowRect.origin.x = clipRect.origin.x
                        rowRect.size.width = clipRect.width
                        rowRect.fill()
                    }
    
                    currentRow += 1
                } while currentRow < rowsToDraw.location + rowsToDraw.length
    
                // Figure out the height of "off the table" rows
                var thisRowHeight = rowHeight
    
                if gridStyleMask.contains(.solidHorizontalGridLineMask) || gridStyleMask.contains(.dashedHorizontalGridLineMask) {
                    thisRowHeight += 2 // Compensate for a grid
                }
    
                // Draw fake rows below the table's last row
                var virtualRowOrigin: CGFloat = 0
                var virtualRowNumber = numberOfRows
    
                if numberOfRows > 0 {
                    let finalRect = rect(ofRow: numberOfRows - 1)
                    virtualRowOrigin = finalRect.origin.y + finalRect.height
                }
    
                repeat {
                    if virtualRowNumber % 2 != 0 {
                        // This is an alternate row
                        let virtualRowRect = NSRect(x: clipRect.origin.x, y: virtualRowOrigin, width: clipRect.width, height: thisRowHeight)
                        virtualRowRect.fill()
                    }
    
                    virtualRowNumber += 1
                    virtualRowOrigin += thisRowHeight
                } while virtualRowOrigin < clipRect.origin.y + clipRect.size.height
    
                // Draw fake rows above the table's first row
                virtualRowOrigin = -1 * thisRowHeight
                virtualRowNumber = -1
    
                repeat {
                    if abs(virtualRowNumber) % 2 != 0 {
                        // This is an alternate row
                        let virtualRowRect = NSRect(x: clipRect.origin.x, y: virtualRowOrigin, width: clipRect.width, height: thisRowHeight)
                        virtualRowRect.fill()
                    }
    
                    virtualRowNumber -= 1
                    virtualRowOrigin -= thisRowHeight
                } while virtualRowOrigin + thisRowHeight > clipRect.origin.y
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-28 17:48

    If you wish to set a custom color paired with the data in each row, I found this way of doing so, thanks to the posts here above, and this solution is also working to implement a custom alternate row color ( except for the empty rows ) :

    create a subclass of NSTableView :

    ColoredRowTableView.h

       @protocol ColoredRowTableViewDelegate <NSTableViewDelegate>
       -(NSColor *)colorForRow:(NSInteger)row;
       @end
       @interface ColoredRowTableView : NSTableView
       @end
    

    in ColoredRowTableView.m

    - (void)drawRow:(NSInteger)row clipRect:(NSRect)clipRect
    {
        if (row == [self selectedRow])
        {
            [super drawRow:row clipRect:clipRect];
             return;
        }
        NSColor *color = [(id<ColoredRowTableViewDelegate>)[self delegate] colorForRow:row];
        [color setFill];
        NSRectFill([self rectOfRow:row]);
        [super drawRow:row clipRect:clipRect];
    }
    

    then in your table view delegate :

    #import "ColoredRowTableView.h"
    @interface MyTableViewDelegate : NSViewController <ColoredRowTableViewDelegate>
    // instead of <NSTableViewDelegate>
    

    implement the colorForRow: method in your delegate. If the goal is only to provide alternate row it can return a color based on the row number, if it is even or odd. Also don't forget to change the class of your table view to ColoredRowTableView in interface builder

    0 讨论(0)
提交回复
热议问题