cocoa - ¿Cómo cambiar el color del texto NSTextField en la selección de fila?
(6)
Para el cacao, tengo un NSTableView configurado para ser basado en la vista. Cuando se selecciona una fila, los campos de texto cambian su color a blanco. ¿Cómo lo mantengo negro?
También debo tener en cuenta que el resaltado está establecido en la Lista de fuentes (hace lo mismo en Regular).
Fila no seleccionada
Fila seleccionada
Esperaba algo similar a la configuración del estado para iOS:
Esto se sugirió en la sesión 120 de la WWDC 2011 pero está un poco retrasado, así que no lo voy a usar. Aunque puede funcionar para alguien más.
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
[tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row){
NSTableCellView *cellView = [rowView viewAtColumn:0];
if(rowView.selected){
cellView.textField.font = [NSFont boldSystemFontOfSize:14];
}else{
cellView.textField.font = [NSFont systemFontOfSize:14];
}
}];
}
Basándome en la respuesta de @ sabes, creé esta subclase NSTextFieldCell
que puede usar para configurar los colores de texto personalizados cuando se selecciona o se deselecciona una fila. Puede establecer la subclase de la celda del campo de texto relevante en IB.
@interface SNBlueTextFieldCell : NSTextFieldCell
@end
@implementation SNBlueTextFieldCell
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
[self setTextColor:(backgroundStyle==NSBackgroundStyleDark ? [NSColor blackColor] : [NSColor blueColor])];
}
@end
Dependiendo de por qué necesita hacer esto, hay 2 enfoques.
Puede subclasificar NSTableRowView
y anular -[NSTableRowView interiorBackgroundStyle]
para devolver NSBackgroundStyleLight
. Esto le dirá a las celdas que están en un fondo claro y que dibuje un texto oscuro, que será negro.
La otra forma es NSTableCellView
subclase NSTableCellView
y anular -[NSTableCellView setBackgroundStyle:]
y configurar los colores allí mismo.
No hay necesidad de código personalizado para lograr eso.
Simplemente configure el color de la etiqueta como "color de la etiqueta" en Interface Builder. La cosa blanca / negra automática solo funciona si la etiqueta tiene el "Color de texto de control" establecido y está en un NSTableCellView.
Para mi aplicación Swift, ninguna de las anteriores parecía funcionar correctamente. Este método maneja el enfoque de pérdida de NSTableView correctamente y cuando la ventana no es la ventana clave pero la celda aún está seleccionada.
Dentro de la subclase NSTableCellView
use lo siguiente:
override var backgroundStyle: NSView.BackgroundStyle {
willSet {
if newValue == .dark {
title.textColor = NSColor.white
} else {
title.textColor = NSColor.labelColor
}
}
}
Se me ocurrió una solución diferente. Subclasificar NSTableCellView hubiera estado bien si Cocoa fuera compatible con @IBOutletCollection. Porque entonces podría tener una subclase de celda que tenga una matriz de todos los NSTextFields en la celda. Pero como tenía muchas clases de celdas con números variables de NSTextFields, no me gustó esta opción. En su lugar, eché un vistazo a la documentación de Apple para la propiedad backgroundStyle
en NSTableCellView.
La implementación predeterminada reenvía automáticamente las llamadas a todas las subvistas que implementan setBackgroundStyle: o son un NSControl, que tienen clases de NSCell que responden a backgroundStyle.
Si mis TextFields implementan setBackgroundStyle, entonces deberían recibir una notificación cuando cambie la selección de celda. Sin embargo, este reenvío del estilo de fondo no es recursivo. Debido a que mis NSTextFields estaban dentro de NSStackViews, no estaban recibiendo el mensaje. Para solucionar esto, acabo de escribir una extensión para implementar setBackgroundStyle en todos los NSViews. Simplemente reenvía el mensaje. Por último, agregué una extensión a NSTextField para implementar este método. Desde esta extensión, cambio el color del texto y llamo super. Esta solución también es buena porque no se necesitan subclases. No hay subclases de NSTableCellView o de NSTextField.
Agregar esta funcionalidad a todas las vistas y a todos los NSTextFields podría causar problemas con los NSTextFields que no se encuentren en NSTableViews cambiando de color inesperadamente. Pero hasta ahora, solo los que están dentro de mi TableViews / OutlineViews están cambiando de color y eso es exactamente lo que estaba buscando. Si ve que los campos de texto cambian de color que no espera, puede subclasificar NSTextField e implementar un reemplazo de setBackgroundStyle solo en esa subclase en lugar de agregarlo a todos los NSTextFields.
El código en Swift 3 que utilicé está pegado a continuación.
extension NSView {
func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
for view in self.subviews {
view.setBackgroundStyle(newValue)
}
}
}
extension NSTextField {
override func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
switch newValue {
case .dark:
self.textColor = NSColor.controlLightHighlightColor
case .light, .lowered, .raised:
self.textColor = NSColor.labelColor
}
super.setBackgroundStyle(newValue)
}
}
Sobrescriba NSTableCellView y agregue este método para cambiar el color del texto cuando se selecciona la celda.
- (void) setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
{
NSTableRowView *row = (NSTableRowView*)self.superview;
if (row.isSelected) {
self.textField.textColor = [NSColor blackColor];
} else {
self.textField.textColor = [NSColor whiteColor];
}
}