objective c - Cambiar NSTableView colores de fila alternativos
objective-c cocoa (7)
Encontré una mejor manera de hacerlo here . Ese método anula el método highlightSelectionInClipRect: en una subclase NSTableView para que pueda usar el color que desee para las filas alternas. No es tan intrincado como usar una categoría de NSColor, y solo afecta las vistas de tabla que elija.
Estoy usando la opción "Filas alternas" en Interface Builder para obtener colores de fila alternativos en un NSTableView. ¿Hay alguna manera de cambiar los colores de las filas alternas?
La answer funcionó perfectamente para mí.
Aquí está, refactorizado para Swift:
import Foundation
import Cocoa
import AppKit
public class SubclassedTableView : NSTableView {
private func
alternateBackgroundColor() -> NSColor? {
return NSColor.redColor() // Return any color you like
}
public override func
drawBackgroundInClipRect(clipRect: NSRect) {
if alternateBackgroundColor() == nil {
// If we didn''t set the alternate colour, fall back to the default behaviour
super.drawBackgroundInClipRect(clipRect)
} else {
// Fill in the background colour
self.backgroundColor.set()
NSRectFill(clipRect)
// Check if we should be drawing alternating coloured rows
if usesAlternatingRowBackgroundColors {
// Set the alternating background colour
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.size.height
let rowsToDraw = rowsInRect(checkRect)
var curRow = rowsToDraw.location
repeat {
if curRow % 2 != 0 {
// This is an alternate row
var rowRect = rectOfRow(curRow)
rowRect.origin.x = clipRect.origin.x
rowRect.size.width = clipRect.size.width
NSRectFill(rowRect)
}
curRow++
} while curRow < rowsToDraw.location + rowsToDraw.length
// Figure out the height of "off the table" rows
var thisRowHeight = rowHeight
if gridStyleMask.contains(NSTableViewGridLineStyle.SolidHorizontalGridLineMask)
|| gridStyleMask.contains(NSTableViewGridLineStyle.DashedHorizontalGridLineMask) {
thisRowHeight += 2.0 // Compensate for a grid
}
// Draw fake rows below the table''s last row
var virtualRowOrigin = 0.0 as CGFloat
var virtualRowNumber = numberOfRows
if numberOfRows > 0 {
let finalRect = rectOfRow(numberOfRows-1)
virtualRowOrigin = finalRect.origin.y + finalRect.size.height
}
repeat {
if virtualRowNumber % 2 != 0 {
// This is an alternate row
let virtualRowRect = NSRect(x: clipRect.origin.x, y: virtualRowOrigin, width: clipRect.size.width, height: thisRowHeight)
NSRectFill(virtualRowRect)
}
virtualRowNumber++
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.size.width, height: thisRowHeight)
NSRectFill(virtualRowRect)
}
virtualRowNumber--
virtualRowOrigin -= thisRowHeight
} while virtualRowOrigin + thisRowHeight > clipRect.origin.y
}
}
}
}
No estoy seguro de cómo se agregó recientemente, o si es tan flexible como lo necesita, pero me di cuenta de que puede especificar filas "Alternantes" en Interface Builder en Xcode 4.6 (y posiblemente antes).
- Abra su pluma en Xcode y seleccione su
NSTableView
oNSOutlineView
- Mostrar el inspector de atributos en el panel Utilidades (⎇⌘4)
- Observe la casilla de verificación
Highlight Alternating Rows
.
No hay una propiedad configurable para esto, sin embargo, puede responder al método delegado -tableView:willDisplayCell:forTableColumn:row:
y establecer el color de fondo de la celda según la uniformidad del número de fila.
Quería una solución que funcionara como la NSTableView
normal, que incluye soporte para desplazamiento elástico y eso, así que creé una subclase NSTableView
que tiene una propiedad NSColor*
llamada alternateBackgroundColor
, y luego -drawBackgroundColorInClipRect:
método -drawBackgroundColorInClipRect:
método así:
- (void) drawBackgroundInClipRect:(NSRect)clipRect {
if([self alternateBackgroundColor] == nil) {
// If we didn''t set the alternate colour, fall back to the default behaviour
[super drawBackgroundInClipRect:clipRect];
} else {
// Fill in the background colour
[[self backgroundColor] set];
NSRectFill(clipRect);
// Check if we should be drawing alternating coloured rows
if([self alternateBackgroundColor] && [self usesAlternatingRowBackgroundColors]) {
// Set the alternating background colour
[[self alternateBackgroundColor] set];
// Go through all of the intersected rows and draw their rects
NSRect checkRect = [self bounds];
checkRect.origin.y = clipRect.origin.y;
checkRect.size.height = clipRect.size.height;
NSRange rowsToDraw = [self rowsInRect:checkRect];
NSUInteger curRow = rowsToDraw.location;
while(curRow < rowsToDraw.location + rowsToDraw.length) {
if(curRow % 2 != 0) {
// This is an alternate row
NSRect rowRect = [self rectOfRow:curRow];
rowRect.origin.x = clipRect.origin.x;
rowRect.size.width = clipRect.size.width;
NSRectFill(rowRect);
}
curRow++;
}
// Figure out the height of "off the table" rows
CGFloat rowHeight = [self rowHeight];
if( ([self gridStyleMask] & NSTableViewSolidHorizontalGridLineMask) == NSTableViewSolidHorizontalGridLineMask
|| ([self gridStyleMask] & NSTableViewDashedHorizontalGridLineMask) == NSTableViewDashedHorizontalGridLineMask) {
rowHeight += 2.0f; // Compensate for a grid
}
// Draw fake rows below the table''s last row
CGFloat virtualRowOrigin = 0.0f;
NSInteger virtualRowNumber = [self numberOfRows];
if([self numberOfRows] > 0) {
NSRect finalRect = [self rectOfRow:[self numberOfRows]-1];
virtualRowOrigin = finalRect.origin.y + finalRect.size.height;
}
while(virtualRowOrigin < clipRect.origin.y + clipRect.size.height) {
if(virtualRowNumber % 2 != 0) {
// This is an alternate row
NSRect virtualRowRect = NSMakeRect(clipRect.origin.x,virtualRowOrigin,clipRect.size.width,rowHeight);
NSRectFill(virtualRowRect);
}
virtualRowNumber++;
virtualRowOrigin += rowHeight;
}
// Draw fake rows above the table''s first row
virtualRowOrigin = -1 * rowHeight;
virtualRowNumber = -1;
while(virtualRowOrigin + rowHeight > clipRect.origin.y) {
if(abs(virtualRowNumber) % 2 != 0) {
// This is an alternate row
NSRect virtualRowRect = NSMakeRect(clipRect.origin.x,virtualRowOrigin,clipRect.size.width,rowHeight);
NSRectFill(virtualRowRect);
}
virtualRowNumber--;
virtualRowOrigin -= rowHeight;
}
}
}
}
Subclasificé NSTableView e implementé drawRow: clipRect: como esto ...
- (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];
}
Parece funcionar, pero es tan simple que me pregunto si me estoy perdiendo algo.
Si desea utilizar una forma no documentada, NSColor
una categoría de NSColor
y anule _blueAlternatingRowColor
esta manera:
@implementation NSColor (ColorChangingFun)
+(NSColor*)_blueAlternatingRowColor
{
return [NSColor redColor];
}
@end
o para cambiar ambos colores, anule controlAlternatingRowBackgroundColors
para devolver un conjunto de colores que desee alternar.
@implementation NSColor (ColorChangingFun)
+(NSArray*)controlAlternatingRowBackgroundColors
{
return [NSArray arrayWithObjects:[NSColor redColor], [NSColor greenColor], nil];
}
@end