选择在NSCollectionView中突出显示

Hoo*_*cat 32 cocoa objective-c nsview nscollectionview nscollectionviewitem

我有NSCollectionView一个小问题但很关键的例外.获取并突出显示集合中的所选项目.

在Snow Leopard之前我已经完成了所有这些工作,但是有些东西似乎发生了变化,我无法完全按照它进行操作,所以我把我的NSCollectionView右手放回基本测试并按照Apple的文档创建了一个NSCollectionView:

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

根据快速入门指南,集合视图可以正常工作.但是,本指南不讨论除了以外的选择"There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected".

以此为例,我进入了将Array Controller NSCollectionView与控制器键绑定的下一步selectionIndexes,认为这将绑定我NSCollectionView在阵列控制器之间做出的任何选择,从而触发KVO通知.我还设置了NSCollectionView在IB中可选择.

似乎没有选择委托,NSCollectionView并且与大多数Cocoa UI视图不同,似乎没有默认的选定突出显示.

所以我的问题实际上归结为一个相关的问题,但有两个截然不同的问题.

  1. 如何捕获项目的选择?
  2. 如何显示项目的突出显示?

NSCollectionView编程指南似乎很少,而且大多数通过Google搜索似乎都会提升Snow Leopard之前的实现,或者在单独的XIB文件中使用该视图.

对于后者(视图的单独XIB文件),我不明白为什么这应该是先决条件,否则我会怀疑Apple不会将视图包含在与集合视图项相同的包中.

我知道这将是一个"无法看到木头为树"的问题 - 所以我已经为"doh!"做好了准备.时刻.

像往常一样,任何和所有帮助非常感谢.

更新1

好的,所以我想找到所选的项目,但尚未确定突出显示.有兴趣计算所选项目(假设您正在关注Apple指南):

在控制器中(在我的测试用例中,App Delegate)我添加了以下内容:

在awakeFromNib中

[personArrayController addObserver:self
       forKeyPath:@"selectionIndexes" 
       options:NSKeyValueObservingOptionNew
       context:nil];
Run Code Online (Sandbox Code Playgroud)

新方法

-(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
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

不要忘记对非GC进行dealloc

-(void)dealloc
{
    [personArrayController removeObserver:self 
                               forKeyPath:@"selectionIndexes"];
    [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

仍在搜索高亮分辨率......

更新2

接受Macatomy的建议,但仍有问题.发布相关的类方法,看看我哪里出错了.

MyView.h

#import <Cocoa/Cocoa.h>

@interface MyView : NSView {
    BOOL selected;
}

@property (readwrite) BOOL selected;

@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

MyCollectionViewItem.h

#import <Cocoa/Cocoa.h>
@class MyView;

@interface MyCollectionViewItem : NSCollectionViewItem {

}

@end
Run Code Online (Sandbox Code Playgroud)

"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
Run Code Online (Sandbox Code Playgroud)

小智 33

如果不同的背景颜色足以作为突出显示,则可以简单地使用NSBox作为集合项视图的根项.使用您选择的高亮颜色填充NSBox.将NSBox设置为Custom,这样填充就可以了.将NSBox设置为透明.

将NSBox的transparency属性绑定到File Owner(Collection Item)的selected属性.将透明绑定的值转换器设置为NSNegateBoolean.

我试图附加界面生成器截图但我被拒绝了bcos我是新手:-(


ind*_*gie 25

它不是很难做到.确保在Interface Builder中为NSCollectionView启用"选择".然后在您用于原型视图的NSView子类中,声明一个名为"selected"的属性:

@property (readwrite) BOOL selected;
Run Code Online (Sandbox Code Playgroud)

此处更新的代码:(增加了超级电话)

子类NSCollectionViewItem和override -setSelected:

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

然后,您需要在原型视图的drawRect:方法中添加代码以绘制突出显示:

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

这只是在选择时以蓝色填充视图,但可以自定义以任何方式绘制突出显示.我在我自己的应用程序中使用了它,它运行得很好.

  • @Macatomy,@ Hopigancat:您应该使用`[NSColor alternateSelectedControlColor]`,而不是像[NSColor blueColor]`这样的硬编码颜色.我们中的一些人更喜欢蓝色以外的选择亮点. (8认同)

Gas*_*enc 5

如果您没有为原型视图继承 NSView,您也可以采用另一种方式。

在您的子类 NSCollectionViewItem 覆盖中 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;
}
Run Code Online (Sandbox Code Playgroud)

当然,正如我之前的所有智者所说,确保为 Interface Builder 中的 NSCollectionView 启用“选择”。


onm*_*133 5

在您的NSCollectionViewItem子类中,覆盖isSelected并更改图层的背景颜色。在 macOS 10.14 和 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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)