我有一个工作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"
以外的选择。
以此为例,我进入下一步,使用控制器键NSCollectionView
将阵列控制器绑定到selectionIndexes
,认为这将绑定{{1}之间的任何选择和数组控制器,从而触发KVO通知。我还将NSCollectionView
设置为可在IB中选择。
似乎没有NSCollectionView
的选择委托,与大多数Cocoa UI视图不同,似乎没有默认选择的突出显示。
所以我的问题实际上归结为一个相关问题,但有两个截然不同的问题。
NSCollectionView
的编程指南似乎很少,而且大多数通过Google搜索似乎都会提升Snow Leopard之前的实现,或者在单独的XIB文件中使用该视图。
对于后者(视图的单独XIB文件),我不明白为什么这应该是先决条件,否则我会怀疑Apple不会将视图包含在与集合视图项相同的包中
我知道这将是一个“看不见木头为树”的问题 - 所以我已经准备好了“doh!”时刻。
像往常一样,任何人都非常感激。
更新1
好的,所以我想找到所选的项目,但尚未确定突出显示。有兴趣计算所选项目(假设您正在关注Apple指南):
在控制器中(在我的测试用例中是App Delegate),我添加了以下内容:
在awakeFromNib
中NSCollectionView
新方法
[personArrayController addObserver:self
forKeyPath:@"selectionIndexes"
options:NSKeyValueObservingOptionNew
context:nil];
不要忘记为非GC发送dealloc
-(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
}
}
}
仍在寻找高光分辨率......
更新2
接受了Macatomy的建议,但仍有问题。发布相关的课程方法,看看我哪里出错了。
MyView.h
-(void)dealloc
{
[personArrayController removeObserver:self
forKeyPath:@"selectionIndexes"];
[super dealloc];
}
MyView.m
#import <Cocoa/Cocoa.h>
@interface MyView : NSView {
BOOL selected;
}
@property (readwrite) BOOL selected;
@end
MyCollectionViewItem.h
#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.m *
#import <Cocoa/Cocoa.h>
@class MyView;
@interface MyCollectionViewItem : NSCollectionViewItem {
}
@end
答案 0 :(得分:33)
如果不同的背景颜色足以作为突出显示,您可以简单地使用NSBox作为集合项视图的根项。 使用您选择的高亮颜色填充NSBox。 将NSBox设置为Custom,这样填充就可以了。 将NSBox设置为透明。
将NSBox的transparency属性绑定到File Owner(Collection Item)的selected属性 将透明绑定的值转换器设置为NSNegateBoolean。
我试图附加界面生成器截图,但我被拒绝了bcos我是新手: - (
答案 1 :(得分:25)
不难做到。确保在Interface Builder中为NSCollectionView启用“选择”。然后在您用于原型视图的NSView子类中,声明一个名为“selected”的属性:
@property (readwrite) BOOL selected;
此处更新的代码:(添加超级电话)
子类NSCollectionViewItem和override -setSelected:
- (void)setSelected:(BOOL)flag
{
[super setSelected:flag];
[(PrototypeView*)[self view] setSelected:flag];
[(PrototypeView*)[self view] setNeedsDisplay:YES];
}
然后,您需要在原型视图的drawRect:方法中添加代码以绘制突出显示:
- (void)drawRect:(NSRect)dirtyRect
{
if (selected) {
[[NSColor blueColor] set];
NSRectFill([self bounds]);
}
}
只需在选中时以蓝色填充视图,但可以自定义以任意方式绘制高光。我已经在我自己的应用程序中使用了它并且效果很好。
答案 2 :(得分:3)
如果你没有为你的原型视图继承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;
}
当然,正如我之前所有聪明人所说的那样,确保在Interface Builder中为NSCollectionView启用了“Selection”。
答案 3 :(得分:2)
由于现有的答案对我来说都不是很好,所以这是我的看法。将CollectionView项的子类更改为SelectableCollectionViewItem。这是它的代码。附带一个可绑定的textColor属性,用于将文本标签textColor绑定到。
@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];
}
答案 4 :(得分:1)
在我的情况下,我想要一个图像(复选标记)来表示对象的选择。将ImageWell拖动到Collection Item nib。设置所需的图像并将其标记为隐藏。转到绑定检查器并将隐藏属性绑定到Collection View Item。
(在我的情况下,我为CollectionViewItem创建了一个单独的nib,因此它绑定到File的所有者。如果不是这样,并且Item视图与CollectionView位于同一个nib中,则绑定到集合查看项目)
将模型关键路径设置为selected
,将值转换设置为NSNegateBoolean
。现在,无论何时选择单个单元格/项目,图像都将可见,因此表明选择。
添加到Alter的回答。
将NSBox设置为根项目。只需创建一个新的IB文档(比如CollectionItem)并将NSBox拖到空白区域。现在在框中添加所需的所有元素。现在点击文件所有者,将自定义类设置为NSCollectionViewItem
。
在添加了NSCollectionView
的笔尖中,更改CollectionViewItem
的笔尖名称
在NSBox中,将其余元素绑定到Files Owner
。对于标签,它将类似于:
现在要将高亮颜色设置为答案中提到的 Alter ,在“填充颜色”选项中设置所需的颜色组合,将NSBox
设置为透明并绑定透明度属性,如下所示:
现在,当选择了集合视图项时,您应该能够看到框的填充颜色。
答案 5 :(得分:1)
在您的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
}
}
}
答案 6 :(得分:0)
这太棒了,非常感谢!我正在努力解决这个问题!
向其他人澄清:
[(PrototypeView*)[self view] setSelected:flag];
[(PrototypeView*)[self view] setNeedsDisplay:YES];
将PrototypeView *替换为原型类名称。
答案 7 :(得分:0)
如果您正在寻找更新的Swift解决方案see this response。
class MyViewItem: NSCollectionViewItem {
override var isSelected: Bool {
didSet {
self.view.layer?.backgroundColor = (isSelected ? NSColor.blue.cgColor : NSColor.clear.cgColor)
}
}
etc...
}
答案 8 :(得分:0)
这是带有选择的完整Swift NSCollectionViewItem。不要忘记在IB或通过编程将NSCollectioView设置为可选。
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
}
}