我正在为一个项目使用 NSOutlineView,但似乎无法弄清楚两件事:
- 如何删除树节点的显示三角形。iTunes 之类的应用似乎可以做到这一点:
是否有某种用于此的 NSOutlineView Delegate 方法?或者它需要一个子类?
- 如何禁用项目的缩进。我试过使用setIndentationPerLevel:并将其设置为 0,以及在 Interface Builder 中将列缩进更改为 0,但它似乎没有任何效果。
我正在为一个项目使用 NSOutlineView,但似乎无法弄清楚两件事:
是否有某种用于此的 NSOutlineView Delegate 方法?或者它需要一个子类?
你在这里遇到了对的人。就在一周前,我不得不解决这个问题。
删除显示三角形:在您的子类中实现该frameOfOutlineCellAtRow:
方法NSOutlineView
并返回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
结果:
使用PXSourceList。这是您正在寻找的带有非常好的 api 的样式。
指定每个级别的意图的正确方法是覆盖indentationPerLevel
NSOutlineView。
class NoIndentOutlineView: NSOutlineView {
override var indentationPerLevel: CGFloat {
get {
return 0;
}
set {
// Do nothing
}
}
}
这将确保孩子与父母有相同的缩进。
这是关于隐藏披露按钮的。如果您希望将其全局隐藏在可扩展项目上,可以这样做:
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
函数。
我知道 q 是 obj-c 的。我只需要解决这个问题,我的项目很快。
以上是OP询问的很好的答案-删除了披露三角形及其占据的空间。要实现'列表不展开且所有项在同一级别',也就是他们所追求的效果,只需将一些顶级项放入作为数据源的数组中并实现
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
return false
}
我在 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)
}
}
}
确保在数据源方法中返回 YourHeaderCellClass 项。
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any