objective-c cocoa nsview nscollectionview nscollectionviewitem

objective c - Resaltado de selección en NSCollectionView



objective-c cocoa (6)

Tengo un NSCollectionView funciona con una excepción menor, pero crítica. Obtener y resaltar el elemento seleccionado dentro de la colección.

He tenido todo esto funcionando antes de Snow Leopard, pero algo parece haber cambiado y no puedo NSCollectionView , así que volví a llevar mi NSCollectionView a una prueba básica y seguí la documentación de Apple para crear un NSCollectionView aquí. :

http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/CollectionViews/Introduction/Introduction.html

La vista de la colección funciona bien siguiendo la guía de inicio rápido. Sin embargo, esta guía no analiza la selección más allá de "There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected" .

Usando esto como ejemplo, pasé al siguiente paso de vincular el Controlador de NSCollectionView al NSCollectionView con la clave del controlador selectionIndexes , pensando que esto vincularía cualquier selección que realice entre NSCollectionView y el controlador de matriz y, por lo tanto, desencadenaría una notificación de KVO. También configuré NSCollectionView para que se pueda seleccionar en IB.

Parece que no hay un delegado de selección para NSCollectionView y, a diferencia de la mayoría de las vistas de la interfaz de usuario de Cocoa, parece que no hay un resaltado seleccionado por defecto.

Entonces mi problema realmente se reduce a un problema relacionado, pero dos preguntas distintas.

  1. ¿Cómo capturo una selección de un artículo?
  2. ¿Cómo se muestra un resaltado de un elemento?

NSCollectionView guías de programación de NSCollectionView parecen ser pocas y distantes, y la mayoría de las búsquedas a través de Google parecen arrancar las implementaciones anteriores a Snow Leopard, o usar la vista en un archivo XIB separado.

Para este último (archivo XIB separado para la vista), no veo por qué esto debería ser un requisito previo, de lo contrario, hubiera sospechado que Apple no hubiera incluido la vista en el mismo paquete que el elemento de vista de colección.

Sé que esto va a ser un problema de "no puedo ver la madera por los árboles", así que estoy preparado para el "¡do!" momento.

Como de costumbre, cualquier ayuda fue muy apreciada.

Actualización 1

OK, así que pensé en encontrar los artículos seleccionados, pero todavía tengo que calcular el resaltado. Para los interesados ​​en calcular los elementos seleccionados (suponiendo que sigas la guía de Apple):

En el controlador (en mi caso de prueba, el delegado de la aplicación) agregué lo siguiente:

En awakeFromNib

[personArrayController addObserver:self forKeyPath:@"selectionIndexes" options:NSKeyValueObservingOptionNew context:nil];

Nuevo método

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if([keyPath isEqualTo:@"selectionIndexes"]) { if([[personArrayController selectedObjects] count] > 0) { if ([[personArrayController selectedObjects] count] == 1) { personModel * pm = (PersonModel *) [[personArrayController selectedObjects] objectAtIndex:0]; NSLog(@"Only 1 selected: %@", [pm name]); } else { // More than one selected - iterate if need be } } }

No se olvide de tratarloc para no GC

-(void)dealloc { [personArrayController removeObserver:self forKeyPath:@"selectionIndexes"]; [super dealloc]; }

Sigue buscando la resolución de resaltado ...

Actualización 2

Tomó el consejo de Macatomy pero todavía tenía un problema. Publicando los métodos de clase relevantes para ver dónde me he equivocado.

MyView.h

#import <Cocoa/Cocoa.h> @interface MyView : NSView { BOOL selected; } @property (readwrite) BOOL selected; @end

MyView.m

#import "MyView.h" @implementation MyView @synthesize selected; -(id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code here. } return self; } -(void)drawRect:(NSRect)dirtyRect { NSRect outerFrame = NSMakeRect(0, 0, 143, 104); NSRect selectedFrame = NSInsetRect(outerFrame, 2, 2); if (selected) [[NSColor yellowColor] set]; else [[NSColor redColor] set]; [NSBezierPath strokeRect:selectedFrame]; } @end

MyCollectionViewItem.h

#import <Cocoa/Cocoa.h> @class MyView; @interface MyCollectionViewItem : NSCollectionViewItem { } @end

"MyCollectionViewItem.m *

#import "MyCollectionViewItem.h" #import "MyView.h" @implementation MyCollectionViewItem -(void)setSelected:(BOOL)flag { [(MyView *)[self view] setSelected:flag]; [(MyView *)[self view] setNeedsDisplay:YES]; } @end


Como ninguna de las respuestas existentes funcionó muy bien para mí, aquí está mi opinión sobre esto. Cambie la subclase del elemento CollectionView a SelectableCollectionViewItem. Aquí está su código. Viene con una propiedad enlatable textColor para enganchar su etiqueta de texto textColor binding a.

@implementation SelectableCollectionViewItem + (NSSet *)keyPathsForValuesAffectingTextColor { return [NSSet setWithObjects:@"selected", nil]; } - (void)viewDidLoad { [super viewDidLoad]; self.view.wantsLayer = YES; } - (void) viewDidAppear { // seems the inital selection state is not done by Apple in a KVO compliant manner, update background color manually [self updateBackgroundColorForSelectionState:self.isSelected]; } - (void)updateBackgroundColorForSelectionState:(BOOL)flag { if (flag) { self.view.layer.backgroundColor = [[NSColor alternateSelectedControlColor] CGColor]; } else { self.view.layer.backgroundColor = [[NSColor clearColor] CGColor]; } } - (void)setSelected:(BOOL)flag { [super setSelected:flag]; [self updateBackgroundColorForSelectionState:flag]; } - (NSColor*) textColor { return self.selected ? [NSColor whiteColor] : [NSColor textColor]; }


En mi caso, quería una imagen (marca de verificación) para indicar la selección del objeto. Arrastre un ImageWell a la punta del elemento de colección. Establezca la imagen deseada y márquela como oculta. Vaya al inspector de enlaces y enlace el atributo oculto al elemento de vista de colección.

(En mi caso, había creado una plumilla separada para CollectionViewItem, por lo que está enlazada al propietario de File. Si este no es el caso y la vista Item está en la misma punta que CollectionView, entonces se une al Item de la Vista de Colección)

Establezca la ruta de la clave del modelo como selected y el transformador de valor en NSNegateBoolean . Eso es ahora, cada vez que se seleccionan las celdas / elementos individuales, la imagen será visible, lo que indica la selección.

Añadiendo a la respuesta de Alter.

Para establecer NSBox como elemento raíz. Simplemente cree un nuevo documento IB (digamos CollectionItem) y arrastre un NSBox al área vacía. Ahora agregue todos los elementos según sea necesario dentro del cuadro. Ahora haga clic en Propietario de archivo y configure Clase personalizada como NSCollectionViewItem .

Y en la punta donde se agrega NSCollectionView cambie el nombre de punta para CollectionViewItem

En NSBox, vincula los elementos restantes al Files Owner . Para una etiqueta, sería similar a:

Ahora, para obtener el color de resaltado como Alter se menciona en su respuesta, configure la combinación de colores deseada en la opción Color de relleno, configure el NSBox como transparente y vincule el atributo de transparencia de la siguiente manera:

Ahora, cuando se seleccionan Elementos de Vista de Colección, debería poder ver el color de relleno de la caja.


Esto fue increíble, ¡muchas gracias! estaba luchando con esto!

Para aclarar a los demás:

[(PrototypeView*)[self view] setSelected:flag]; [(PrototypeView*)[self view] setNeedsDisplay:YES];

Reemplace PrototypeView * con el nombre del nombre de clase de su prototipo.


No es muy difícil de hacer. Asegúrese de que "Selección" esté habilitado para NSCollectionView en Interface Builder. Luego, en la subclase NSView que está utilizando para su vista de prototipo, declare una propiedad llamada "seleccionada":

@property (readwrite) BOOL selected;

CÓDIGO ACTUALIZADO AQUÍ: (supercarretera añadida)

Subclase NSCollectionViewItem y override -setSelected:

- (void)setSelected:(BOOL)flag { [super setSelected:flag]; [(PrototypeView*)[self view] setSelected:flag]; [(PrototypeView*)[self view] setNeedsDisplay:YES]; }

Luego, debe agregar código en el método drawRect: de su vista de prototipo para resaltar:

- (void)drawRect:(NSRect)dirtyRect { if (selected) { [[NSColor blueColor] set]; NSRectFill([self bounds]); } }

Eso simplemente llena la vista en azul cuando está seleccionada, pero puede personalizarse para dibujar el resaltado de la forma que desee. Lo he usado en mis propias aplicaciones y funciona muy bien.


Si un color de fondo diferente será suficiente como resaltado, simplemente podría usar un NSBox como elemento raíz para su vista de elemento de colección. Llena el NSBox con el color de resalte que elijas. Establezca el NSBox en Personalizado para que el relleno funcione. Establezca el NSBox en transparente.

Vincule el atributo de transparencia de NSBox con el atributo seleccionado de Propietario de archivo (Elemento de recopilación). Establezca el transformador de valor para el enlace transparente a NSNegateBoolean.

Traté de adjuntar capturas de pantalla de Interface Builder pero me rechazaron bcos Soy un novato :-(


También puede ir de otra manera, si no está subclasificando NSView para su vista de prototipo.

En su subclase NSCollectionViewItem, anule setSelected:

- (void)setSelected:(BOOL)selected { [super setSelected:selected]; if (selected) self.view.layer.backgroundColor = [NSColor redColor].CGColor; else self.view.layer.backgroundColor = [NSColor clearColor].CGColor; }

Y, por supuesto, como lo dijeron todos los sabios antes que yo, asegúrese de que "Selección" esté habilitado para NSCollectionView en Interface Builder.