Auswahl Highlight in NSCollectionView
-
23-09-2019 - |
Frage
Ich habe eine Arbeits NSCollectionView
mit einer kleineren, aber kritisch, Ausnahme. Erste und Markieren des ausgewählten Element in der Sammlung.
Ich habe alle hatten diese Arbeit vor Snow Leopard, aber etwas scheint sich geändert zu haben, und ich kann nicht ganz meine Finger legen auf sie, so dass ich meine NSCollectionView
nahm gleich wieder auf ein Basistest und folgte Apples Dokumentation für die Erstellung von ein NSCollectionView hier:
Die Sammlung Ansicht funktioniert gut im Anschluss an die Schnellstartanleitung. Allerdings ist diese Führung nicht Auswahl anders als "There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected"
diskutieren.
Mit diesem als Beispiel ich mit dem nächsten Schritt ging den Array-Controller der Bindung an die NSCollectionView
mit der Controller Schlüssel selectionIndexes
, denkt, dass dies eine beliebige Auswahl binden würde ich zwischen den NSCollectionView
machen und den Array-Controller und damit aus einem KVO Brennen Benachrichtigung. Ich habe auch die NSCollectionView
in IB wählbar sein.
Es scheint keine Auswahl Delegat für NSCollectionView
zu sein, und im Gegensatz zu den meisten Cocoa UI Ansichten, erscheint Highlight nicht standardmäßig aktiviert zu sein.
Also mein Problem kommt auf ein ähnliches Problem wirklich, aber zwei verschiedene Fragen.
- Wie erfasse ich eine Auswahl eines Artikels?
- Wie kann ich ein Highlight eines Artikels?
NSCollectionView
des Programmführern scheinen dünn gesät und die meisten Suchanfragen über Google zu sein scheinen Implementierungen zu ziehen Pre-Snow Leopard oder den Blick in einer separaten XIB-Datei verwenden.
Für letztere (getrennte XIB-Datei für die Ansicht), ich sehe nicht, warum dies eine Voraussetzung sein sollte, sonst hätte ich vermutet habe, dass Apple nicht die Ansicht im gleichen Bündel wie die Sammlungsansicht Artikel enthalten ist, .
Ich weiß, dass dies ein sein wird Problem „kann nicht das Holz für die Bäume sehen“ - „doh“ so bin ich für die vorbereitet Moment.
Wie üblich, jede und alle Hilfe sehr geschätzt.
Update 1
OK, so dachte ich, das ausgewählte Element zu finden (s), aber noch die Markierung Figur. Für die interessiert auf die ausgewählten Elemente Bezifferung (vorausgesetzt, Sie auf das Apple-Führung folgen):
In der Steuerung (in meinem Testfall der App Delegate) Ich habe die folgenden:
In awakeFromNib
[personArrayController addObserver:self
forKeyPath:@"selectionIndexes"
options:NSKeyValueObservingOptionNew
context:nil];
Neue Methode
-(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
}
}
}
Vergessen Sie nicht zu dealloc für nicht-GC
-(void)dealloc
{
[personArrayController removeObserver:self
forKeyPath:@"selectionIndexes"];
[super dealloc];
}
Still für die Highlight Auflösung der Suche ...
Update 2
Nahm Macatomy Rat aber noch ein Problem hatte. die entsprechenden Klassenmethoden Posting zu sehen, wo ich weg falsch haben.
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
Lösung
Es ist nicht allzu schwer zu tun. Stellen Sie sicher, „Auswahl“ für die NSCollectionView im Interface Builder aktiviert. Dann in der NSView Unterklasse, die Sie für Ihre Prototyp-Ansicht verwenden, deklarieren Sie eine Eigenschaft namens „ausgewählt“:
@property (readwrite) BOOL selected;
AKTUALISIERT CODE HIER: (hinzugefügt Super Call)
Subclass NSCollectionViewItem und Überschreibung -setSelected:
- (void)setSelected:(BOOL)flag
{
[super setSelected:flag];
[(PrototypeView*)[self view] setSelected:flag];
[(PrototypeView*)[self view] setNeedsDisplay:YES];
}
Dann müssen Sie Code in Ihrem Prototyp Ansicht des drawRect hinzuzufügen: Methode, um die Markierung ziehen:
- (void)drawRect:(NSRect)dirtyRect
{
if (selected) {
[[NSColor blueColor] set];
NSRectFill([self bounds]);
}
}
Das nur einfach die Aussicht in blau füllt, wenn seine ausgewählt, aber das kann angepasst werden der Höhepunkt, wie Sie wollen zu ziehen. Ich habe dies in meinen eigenen Anwendungen verwendet und es funktioniert super.
Andere Tipps
Wenn eine andere Hintergrundfarbe als Highlight ausreicht, könnte man einfach eine NSBox als Root-Element für Dich Auflistelement Ansicht verwenden. Füllen Sie das NSBox mit der Highlight-Farbe Ihrer Wahl. Stellen Sie die NSBox auf Custom so wird die Füllung arbeiten. Stellen Sie den NSBox zu transparent.
Binden Sie die Transparenz-Attribut des NSBox auf das ausgewählte Attribut der Datei-Besitzer (Sammlung Item) Setzen Sie den Wert Transformator für die transparente Bindung an NSNegateBoolean.
Ich habe versucht, Interface Builder Screenshots zu befestigen, aber ich wurde abgelehnt bcos ich ein Neuling bin: - (
Sie können auch einen anderen Weg gehen, wenn Sie nicht NSView für Ihre protoype Ansicht Subklassen.
In Ihrer subclassed NSCollectionViewItem Überschreibung 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;
}
Und natürlich sagte, die von allen den klugen Menschen vor mir, stellen Sie sicher, „Selection“ für die NSCollectionView im Interface Builder aktiviert.
Da keine der vorhandenen Antworten super geklappt gut für mich, hier ist mein nehmen auf sie. Ändern Sie die Unterklasse der Collection Artikel zu SelectableCollectionViewItem. Hier ist es der Code. Kommt mit einer bindungsfähigen Eigenschaft textcolor für Ihre Text Label Textfarbe Bindung an Einhaken.
@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];
}
In meinem Fall wollte ich ein Bild (Häkchen) Auswahl des Objekts anzuzeigen. Ziehen Sie eine Imagewell an den Sammelgegenstand Feder. Stellen Sie das gewünschte Bild und markieren Sie ihn als versteckt. Zum Bindungen Inspektor und binden versteckt Attribut-Sammlung Ansicht Artikel.
(In meinem Fall habe ich eine separate Feder für CollectionViewItem geschaffen hatte, so seine binded auf Datei-Besitzer. Ist dies nicht der Fall ist und Artikelansicht ist in der gleichen Feder wie die Collection dann binden Sammlung View Item)
Set Modell Schlüsselpfad als selected
und Wert Transformator NSNegateBoolean
. Das ist es jetzt, wenn die einzelnen Zellen / Elemente sind das Bild ausgewählt sichtbar sein wird, damit die Auswahl angezeigt wird.
Das Hinzufügen Alten Antwort.
So legen NSBox als Stammelement. Erstellen Sie einfach ein neues IB-Dokument (sagen CollectionItem) und einen NSBox in dem leeren Bereich ziehen. Nun fügen Sie alle Elemente, wie in der Box erforderlich. Jetzt auf Datei-Besitzer klicken und stellen Sie Kundenspezifische Klasse als NSCollectionViewItem
.
Und in der Spitze, wo NSCollectionView
Änderung für CollectionViewItem
die Spitze Namen hinzugefügt wird
In der NSBox, bindet die übrigen Elemente zu Files Owner
. Für ein Etikett wäre es ähnlich sein:
Jetzt die Markierungsfarbe erhalten, wie Alter in seiner Antwort erwähnt, stellen Sie die gewünschte Farbkombination in der Füllfarbe Option, stellen Sie die NSBox
zu transparent und binden die Transparenz-Attribut wie folgt:
Nun, wenn Sammlung Ansicht Artikel ausgewählt werden, sollten Sie in der Lage sein, die Füllfarbe der Box zu sehen.
In Ihrer NSCollectionViewItem
Unterklasse überschreiben isSelected
und ändern Hintergrundfarbe der Schicht. Test in macOS 10.14 und Swift 4.2
class Cell: NSCollectionViewItem {
override func loadView() {
self.view = NSView()
self.view.wantsLayer = true
}
override var isSelected: Bool {
didSet {
self.view.layer?.backgroundColor = isSelected ? NSColor.gray.cgColor : NSColor.clear.cgColor
}
}
}
Das war genial, vielen Dank! Ich war mit diesem zu kämpfen!
Um zu klären, für den anderen:
[(PrototypeView*)[self view] setSelected:flag];
[(PrototypeView*)[self view] setNeedsDisplay:YES];
Ersetzen PrototypeView * mit dem Namen Ihres Prototyp Klassennamen.
Falls Sie graben um für die Lösung Swift aktualisiert, sehen diese Antwort .
class MyViewItem: NSCollectionViewItem {
override var isSelected: Bool {
didSet {
self.view.layer?.backgroundColor = (isSelected ? NSColor.blue.cgColor : NSColor.clear.cgColor)
}
}
etc...
}
Dies ist die komplette Swift NSCollectionViewItem mit Auswahl. Vergessen Sie nicht die NSCollectioView wählbarer in IB oder programmatisch zu setzen. Getestet unter macOS Mojave (10,14) und High Sierra (10.13.6).
import Cocoa
class CollectionViewItem: NSCollectionViewItem {
private var selectionColor : CGColor {
let selectionColor : NSColor = (isSelected ? .alternateSelectedControlColor : .clear)
return selectionColor.cgColor
}
override var isSelected: Bool {
didSet {
super.isSelected = isSelected
updateSelection()
// Do other stuff if needed
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.wantsLayer = true
updateSelection()
}
override func prepareForReuse() {
super.prepareForReuse()
updateSelection()
}
private func updateSelection() {
view.layer?.backgroundColor = self.selectionColor
}
}