将控件/按钮栏添加到配置为源列表的NSOutlineView的底部

Joh*_*lls 9 macos cocoa objective-c nsoutlineview nsbutton

我正在尝试在我的基于NSOutlineView的源列表的底部添加一个按钮栏,如许多Mac应用程序(Apple和第三方)中所示,如以下屏幕截图所示:

Xcode源列表页脚 邮件来源列表页脚

为了以文本方式描述它,控制条共享源列表的特殊样式渐变背景(或在Yosemite,"vibrancy"下),而不重叠任何源列表的内容.为了重现这种效果,到目前为止我尝试了以下方法:

  1. 使用按钮栏的高度添加额外的"填充"到源列表的滚动视图的剪辑视图的底部,并允许栏与源列表视图重叠.这仅适用于按钮栏背景不透明且不会将滚动条移开的情况.
  2. 使用NSBoxes将其背景设置为NSColor源列表的backgroundColor属性提供的背景.这需要大量的强制重绘才能正确绘制(特别是在窗口活动/非活动状态下),否则看起来很完美.使用自定义NSView设置绘制渐变背景时会看到类似的行为.

有没有其他方法可以用来实现这一目标?#2是我能够提供的最接近的但是考虑到它带来的问题,它显然不适合第三方开发人员使用.

在Yosemite中使用Vibrancy这样做应该很简单,需要检查优胜美地并插入NSVisualEffectView带有活力的活动.另一方面,在10.8/10.9下正确......

我可以完全通过使用NSWindow提供的内置底栏绘图来回避这个问题,但颜色合并的方法在视觉上更清晰,更强烈地将控件与其父窗格相关联,并且似乎更多的选择风格这些天更常见.如果可能的话,我想在我自己的应用程序中使用它.

And*_*rew 1

我能够通过子类化 NSView 并使用 KVO 来观察包含窗口的关键状态更改时的颜色变化来实现此工作。由于您提到的原因(活力),它在 10.10 上不起作用,但它在 10.9 上运行得很好。

苹果邮件列表上的源列表背景颜色线程为我解决了这个问题。

界面:

#import <Cocoa/Cocoa.h>

@interface SourceListColoredView : NSView
@end
Run Code Online (Sandbox Code Playgroud)

执行:

#import "SourceListColoredView.h"

@interface SourceListColoredView ()
@property (nonatomic, strong) NSColor *backgroundColor;
@property (nonatomic, assign, getter = isObservingKeyState) BOOL observingKeyState;
@end

@implementation SourceListColoredView

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addWindowKeyStateObservers];
    }
    return self;
}

- (void)awakeFromNib
{
    NSOutlineView *outlineView = [[NSOutlineView alloc] init];
    [outlineView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
    self.backgroundColor = [outlineView backgroundColor];
    [self addWindowKeyStateObservers];
}

- (void)addWindowKeyStateObservers
{
    if (!self.isObservingKeyState) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(redisplay)
                                                     name:NSWindowDidBecomeKeyNotification
                                                   object:[self window]];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(redisplay)
                                                     name:NSWindowDidResignKeyNotification
                                                   object:[self window]];
    }
    self.observingKeyState = YES;
}

- (void)redisplay
{
    [self setNeedsDisplay:YES];
}

- (void)dealloc
{
    if (self.isObservingKeyState) {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:[self window]];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:[self window]];
    }
}

- (void)drawRect:(NSRect)dirtyRect
{
    [_backgroundColor setFill];
    NSRectFill(dirtyRect);
}

@end
Run Code Online (Sandbox Code Playgroud)

您可能必须将 -awakeFromNib 中的代码移至其他位置,具体取决于初始化视图的方式。