向底部添加控制/按钮栏以配置为源列表的NSOutlineView

9

我正在尝试向基于NSOutlineView的源列表底部添加按钮栏,这在许多Mac应用程序中都可以看到(包括苹果和第三方),如以下截图所示:

Xcode Source List Footer Mail Source List Footer

以文字来描述,控制栏与源列表共享特殊样式的渐变背景(或Yosemite下的"活力")而不重叠源列表的任何内容。为了复制这种效果,我目前已经尝试了以下方法:

  1. 向源列表滚动视图的裁剪视图的底部添加额外的"填充",高度与按钮栏相同,并允许栏覆盖源列表视图。只有当按钮栏的背景是不透明的且不会挡住滚动条时才有效。
  2. 使用其背景设置为源列表backgroundColor属性提供的NSColor的NSBoxes。这需要强制重绘很多次才能正确绘制(特别是在窗口活动/非活动状态下),但除此之外看起来完美。使用自定义的NSView设置绘制渐变背景会出现类似的行为。

是否有其他方法可以用于实现这一点?#2 是我能够接近的最好方法,但由于它带来的问题,显然不适用于第三方开发人员。

在Yosemite中使用Vibrancy应该很简单,只需要检查是否为Yosemite并插入打开Vibrancy的NSVisualEffectView即可。然而,在10.8 / 10.9下正确处理它则需要更多的操作……

我可以通过使用NSWindow提供的内置底部栏绘制来完全避免这个问题,但颜色混合的方法在视觉上更干净,更强烈地将控件与其父面板相关联,并且似乎越来越成为当今的首选样式。如果可能的话,我想在我的应用程序中使用它。

3个回答

1
我能通过子类化NSView并使用KVO来观察包含窗口的关键状态变化时的颜色变化,从而使其正常工作。由于亮度效果,它在10.10上无法工作,但在10.9上可以完美地工作。
Apple邮件列表上的Sourcelist background colors主题是解决此问题的方法。 界面:
#import <Cocoa/Cocoa.h>

@interface SourceListColoredView : NSView
@end

实现:

#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

您可能需要根据视图的初始化方式将代码从-awakeFromNib移动到其他位置。

0
你可以通过添加带有Gradient EffectNSButton来简单实现。
查看https://github.com/Perspx/PXSourceList的源代码。
打开View Based Table的XIB,你将可以获得一个示例来实现它。

0
我找到了解决方案: 我像你一样在SplitView左侧的底部放置了一个NSBox。 这是我的视图层次结构:

Hierarchical view of components in Interface Builder

解决方案是在NSBox的检查器中填写正确的参数:

parameters of the box

我在这里将框类型设置为自定义,并将填充颜色设置为白色。

希望我的回答对您有所帮助。


当源列表的内容足以滚动时会发生什么?滚动条有多高?它是重叠还是悬浮在框上?源列表中的项目是否透过框显示? - Ken Thomases
项目中的项并未显示在上方,而是被框隐藏了。滚动条仅会出现在框内。若想查看完整项目,请前往此链接:link - zarghol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接