Hoo*_*cat 32 cocoa objective-c nsview nscollectionview nscollectionviewitem
我有NSCollectionView一个小问题但很关键的例外.获取并突出显示集合中的所选项目.
在Snow Leopard之前我已经完成了所有这些工作,但是有些东西似乎发生了变化,我无法完全按照它进行操作,所以我把我的NSCollectionView右手放回基本测试并按照Apple的文档创建了一个NSCollectionView:
根据快速入门指南,集合视图可以正常工作.但是,本指南不讨论除了以外的选择"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视图不同,似乎没有默认的选定突出显示.
所以我的问题实际上归结为一个相关的问题,但有两个截然不同的问题.
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)
这只是在选择时以蓝色填充视图,但可以自定义以任何方式绘制突出显示.我在我自己的应用程序中使用了它,它运行得很好.
如果您没有为原型视图继承 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 启用“选择”。
在您的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)