我正在为一个项目使用NSOutlineView,但有两个问题无法解决:
- 如何删除树节点的展开三角形。像iTunes这样的应用程序似乎能够做到这一点:
是否有某种NSOutlineView Delegate方法用于此?还是需要对其进行子类化处理?
- 如何禁用项目的缩进。我尝试使用setIndentationPerLevel:并将其设置为0,以及在Interface Builder中将列缩进设置为0,但似乎没有任何效果。
我正在为一个项目使用NSOutlineView,但有两个问题无法解决:
是否有某种NSOutlineView Delegate方法用于此?还是需要对其进行子类化处理?
你找对人了。就在一个星期前,我也曾经遇到过这个问题。
移除披露三角形:在你的NSOutlineView
子类中实现frameOfOutlineCellAtRow:
方法并返回NSZeroRect
(当然只有你想要隐藏特定行的三角形时才需要这样做)。
- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row {
return NSZeroRect;
}
禁用缩进: 大纲视图的标准布局会在最左边预留空间来绘制三角形以便展开项使用。但是你可以通过指定不同的绘制框架来覆盖个别项上的这种行为。你可以通过响应此消息,在子类中实现该功能:
- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
NSRect superFrame = [super frameOfCellAtColumn:column row:row];
if ((column == 0) /* && isGroupRow */) {
return NSMakeRect(0, superFrame.origin.y, [self bounds].size.width, superFrame.size.height);
}
return superFrame;
}
以后参考,隐藏可展开的NSOutlineView项中的披露三角形的最干净和最简单的方法是通过在代理中实现NSOutlineViewDelegate协议的outlineView:shouldShowOutlineCellForItem:方法:
-(BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item
{
// replace this with your logic to determine whether the
// disclosure triangle should be hidden for a particular item
return [item hidesDisclosureTriangle];
}
我不得不将上述两种方法结合起来,因为单独使用outlineView:shouldShowOutlineCellForItem:
不能移除为揭示三角形所保留的空间(但它可以移除三角形本身)。
代理:
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item {
return NO;
}
NSOutlineView的子类:
@implementation ExpandedOutlineView
#define kOutlineCellWidth 11
#define kOutlineMinLeftMargin 6
- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
NSRect superFrame = [super frameOfCellAtColumn:column row:row];
if (column == 0) {
// expand by kOutlineCellWidth to the left to cancel the indent
CGFloat adjustment = kOutlineCellWidth;
// ...but be extra defensive because we have no clue what is going on here
if (superFrame.origin.x - adjustment < kOutlineMinLeftMargin) {
NSLog(@"%@ adjustment amount is incorrect: adjustment = %f, superFrame = %@, kOutlineMinLeftMargin = %f", NSStringFromClass([self class]), (float)adjustment, NSStringFromRect(superFrame), (float)kOutlineMinLeftMargin);
adjustment = MAX(0, superFrame.origin.x - kOutlineMinLeftMargin);
}
return NSMakeRect(superFrame.origin.x - adjustment, superFrame.origin.y, superFrame.size.width + adjustment, superFrame.size.height);
}
return superFrame;
}
@end
结果:
NSOutlineView
没有打开 usesAutomaticRowHeights
,这个功能就可以很好地工作。 - PadraigYES
到PXSourceListDelegate
消息-sourceList:isGroupAlwaysExpanded:
来实现该样式。 - Alex Rozanski指定每个级别的意图的正确方法是通过覆盖 NSOutlineView 的 indentationPerLevel
。
class NoIndentOutlineView: NSOutlineView {
override var indentationPerLevel: CGFloat {
get {
return 0;
}
set {
// Do nothing
}
}
}
这将确保子元素与父元素具有相同的缩进。
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
return false
}
这是关于隐藏披露按钮的问题。如果你想在可展开项上全局隐藏它,可以这样做:
extension NSOutlineView {
override open func makeView(withIdentifier identifier: NSUserInterfaceItemIdentifier, owner: Any?) -> NSView? {
if identifier == NSOutlineView.disclosureButtonIdentifier {
return nil
} else {
return super.makeView(withIdentifier: identifier, owner: owner)
}
}
}
否则,您可以子类化NSOutlineView
并覆盖makeView
函数。
我知道这个问题是针对obj-c的。但我必须解决这个问题,我的项目是Swift。
我在Swift中尝试过这个方法,它可以正常工作。但我不确定这是否是一种合适的方式。在Obj-C中应该有相应的方法:
extension NSTableRowView {
override open func layout() {
super.layout()
if let cell = subviews.first as? NSTableCellView, cell.objectValue is <YourHeaderCellClass> {
subviews.first?.setFrameOrigin(NSZeroPoint)
}
}
}
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any