我有一个NSToolbarItem
使用类似于 Xcode 状态视图的视图。它目前没有标签,但我无法找到一种方法来绘制通常会绘制项目标签的区域。我希望视图能够像 Xcode 状态视图一样扩展到该区域。我知道像素的最底部NSToolbar
超出范围,但我看到其他应用程序绘制到标签区域。有任何想法吗?
编辑:为澄清起见,这是我在 Xcode 中所指的状态视图:
我希望我的视图的边界延伸到工具栏的标签区域之外,就像 Xcode 中的视图一样。
我有一个NSToolbarItem
使用类似于 Xcode 状态视图的视图。它目前没有标签,但我无法找到一种方法来绘制通常会绘制项目标签的区域。我希望视图能够像 Xcode 状态视图一样扩展到该区域。我知道像素的最底部NSToolbar
超出范围,但我看到其他应用程序绘制到标签区域。有任何想法吗?
编辑:为澄清起见,这是我在 Xcode 中所指的状态视图:
我希望我的视图的边界延伸到工具栏的标签区域之外,就像 Xcode 中的视图一样。
NSToolbarItem
Xcode状态视图不是NSView
插入到NSToolbar
.
如果您登录
NSLog(@" %@", [[self.window.contentView superview] subviews]);
你会得到
NSToolbarView 不会自动调整其子视图的大小,因此您在居中时会遇到问题。[self.window.contentView superview]
全屏时不包含工具栏视图。
您可以将所需的视图添加到工具栏的中心,而[self.window.contentView superview]
不是全屏并正确定位。它将自动调整大小并保持居中。当切换到全屏时,将其从中删除并将其[self.window.contentView superview]
添加到中心的 NSToolbarView 中,这样它就会留在工具栏中,并且当您显示状态栏时它也会随着工具栏向下移动。
您可以通过遍历子视图或使用私有方法来获取工具栏视图
[[self.window toolbar] performSelector:@selector(_toolbarView)];
更新:我用调试器做了更多的挖掘,我发现这就是 Xcode 所做的。至少在没有全屏时。
thealch3m1st$ sudo lldb
(lldb) process attach -p 11478
Process 11478 stopped
Executable module set to "/Applications/Xcode.app/Contents/MacOS/Xcode".
Architecture set to: x86_64.
(lldb) po [NSApplication sharedApplication]
(id) $0 = 0x000000040013f5e0 <IDEApplication: 0x40013f5e0>
(lldb) po [$0 mainWindow]
(id) $1 = 0x0000000000000000 <nil>
(lldb) po [$0 windows]
(id) $2 = 0x0000000408278460 <__NSArrayM 0x408278460>(
<IDEWelcomeWindow: 0x40141c1e0>,
<IDEWorkspaceWindow: 0x401ef2780>,
<NSComboBoxWindow: 0x402019be0>,
<NSWindow: 0x4022adc60>,
<IDEOrganizerWindow: 0x402951b20>
)
(lldb) po [$0 windows]
(id) $3 = 0x0000000408820300 <__NSArrayM 0x408820300>(
<IDEWelcomeWindow: 0x40141c1e0>,
<IDEWorkspaceWindow: 0x401ef2780>,
<NSComboBoxWindow: 0x402019be0>,
<NSWindow: 0x4022adc60>,
<IDEOrganizerWindow: 0x402951b20>
)
(lldb) [$3 objectAtIndex:1]
error: '[$3' is not a valid command.
(lldb) po [$3 objectAtIndex:1]
(id) $4 = 0x0000000401ef2780 <IDEWorkspaceWindow: 0x401ef2780>
(lldb) po [$4 contentView]
(id) $5 = 0x0000000401ef0920 <NSView: 0x401ef0920>
(lldb) po [$5 superview]
(id) $6 = 0x0000000401ef2e20 <NSThemeFrame: 0x401ef2e20>
(lldb) po [$6 subviews]
(id) $7 = 0x0000000401ef3800 <__NSArrayM 0x401ef3800>(
<_NSThemeCloseWidget: 0x401ef3120>,
<_NSThemeWidget: 0x401ef3b80>,
<_NSThemeWidget: 0x401ef40e0>,
<NSView: 0x401ef0920>,
<IDEActivityView: 0x4020cd700>,
<_NSThemeFullScreenButton: 0x402017b20>,
(<NSToolbarView: 0x4020192e0>: Xcode.IDEKit.ToolbarDefinition.Workspace),
<DVTDualProxyWindowTitleView: 0x40225e0a0>,
<NSThemeDocumentButton: 0x402698020>
)
(lldb) po [$7 objectAtIndex:4]
(id) $8 = 0x00000004020cd700 <IDEActivityView: 0x4020cd700>
(lldb) [$8 setHidden:YES]
error: '[$8' is not a valid command.
(lldb) po [$8 setHidden:YES]
(id) $9 = 0x0000000000000000 <nil>
(lldb) continue
Process 11478 resuming
(lldb)
活动视图消失了:)
但是在全屏时。它不会将其添加到 NSToolbarView 中,而是将其添加到 NSNextStepFrame 中,这是 NSToolbarView 的超级视图。全屏时,工具栏不包含在窗口的 contentview 超级视图中。我认为这与全屏行为和空间有关。
你必须继承 NSToolbarItem:
- (id)initWithItemIdentifier:(NSString *)itemIdentifier {
self = [super initWithItemIdentifier:itemIdentifier];
if (self) {
self.hideLabel = NO;
}
return self;
}
- (NSView *)view {
NSView *view = [super view];
if (self.hideLabel) {
CGRect frame = view.frame;
frame.size.height = 45.0f;
frame.origin.y = 8.0f;
view.frame = frame;
}
return view;
}
- (NSString *)label {
return self.hideLabel ? @"" : [super label];
}
创建工具栏:
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"Toolbar"];
toolbar.delegate = self;
self.window.toolbar = toolbar;
使用 NSToolbarDelegate 用项目填充工具栏:
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar {
return [NSArray arrayWithObjects:@"Button", @"LCD", NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, nil];
}
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar {
return [NSArray arrayWithObjects:@"Button", NSToolbarFlexibleSpaceItemIdentifier, @"LCD", NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, nil];
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
MyToolbarItem *item = [[MyToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
if ([itemIdentifier isEqualToString:@"LCD"]) {
item.view = self.lcdView;
item.hideLabel = YES;
} else if ([itemIdentifier isEqualToString:@"Button"]) {
item.label = NSLocalizedString(@"Button", nil);
item.image = [NSImage imageNamed:@"Button"];
item.hideLabel = NO;
}
return item;
}
在您将其交给工具栏项之前,液晶视图应该(在这种情况下)高 32 点。如果它更大,工具栏将太高。
Xcode 状态视图实际上是一个浮动在工具栏上的单独窗口。(这很容易测试:按 ⇧⌘4 并按空格来截取窗口的屏幕截图,然后将鼠标悬停在它上面。)
此代码安装一个浮动在工具栏顶部的窗口。
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification {
NSRect winframe = [self.window frame];
NSRect viewrect = NSMakeRect(0, 0, 400, 50);
NSRect winrect = viewrect;
winrect.origin.x = NSMidX(winframe) - NSMidX(winrect);
winrect.origin.y = NSHeight(winframe) - NSHeight(winrect) - 18;
NSWindow* win = [[[NSWindow alloc] initWithContentRect:winrect styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: NO] autorelease];
[win setBackgroundColor:[NSColor clearColor]];
[win setOpaque:NO];
[win setIgnoresMouseEvents:YES];
MyStatusView* v = [[[MyStatusView alloc] initWithFrame:viewrect] autorelease];
[win setContentView: v];
[self.window addChildWindow:win ordered:NSWindowAbove];
}
在标签区域延伸的 iTunes-XCode-LCD 不是NSToolbarItem
. 由于NSToolbar
is not a NSView
,您不能将子视图添加到NSToolbar
实例。但是您可以直接在窗口框架中添加自定义视图,可以通过实例的contentView.superview
属性路径访问!NSWindow
即创建自己的 NSWindowController 子类,并在 'windowDidLoad' 方法中放置一些类似这样的代码:
- (void)windowDidLoad
{
[super windowDidLoad];
NSImage *image = [NSImage imageNamed:@"lcd"];
NSRect lcdFrameRect = NSMakeRect(self.window.frame.size.width / 2 - image.size.width/2, self.window.frame.size.height - image.size.height - 20,
image.size.width, image.size.height);
NSImageView *lcdView = [[NSImageView alloc] initWithFrame: lcdFrameRect];
[lcdView setImage: image];
lcdView.autoresizingMask = NSViewMinYMargin | NSViewMinXMargin | NSViewMaxXMargin;
NSView * contentView = self.window.contentView;
[contentView.superview addSubview: lcdView];
}
此代码在 Lion 的全屏模式下不起作用,因为在全屏模式下不会绘制框架窗口。为了解决这个问题,可以在浮动窗口中移动视图,主窗口的子窗口(只需检查 NSWindow addChildWindow:ordered: 方法)。