4

为文本视图启用“检查器栏”很容易,因此屏幕顶部会出现一个带有各种格式按钮的栏。(虽然我有一些困惑,直到我学会确保我在滚动视图中选择文本视图,而不是滚动视图本身)。我可以以编程方式使用 [textView setUsesInspectorBar:YES] 或转到 Attributes Inspector 并选中“Uses”部分中的“Inspector Bar”框。

我的问题是,我怎样才能进一步控制检查栏?我无法在 XCode 文档或在线查找有关它的信息。我希望能够将其放置在屏幕上的不同位置。能够选择栏中的特定控件也很棒。

4

4 回答 4

5

答案是,您并不打算进一步控制检查栏。文档中什么都没有,因为,好吧,什么都没有。苹果的说法,使用它或不使用它。

但是,如果您深入研究一下,您会发现检查器栏是一个非常有趣的控件。它不显示为文本视图的一部分,而是(私下)嵌入在“窗口视图”本身中。当我说“窗口视图”时,我指的是内容视图的超级视图。

如果您列出该“窗口视图”的子视图:

NSLog(@"%@", [self.testTextView.window.contentView superview].subviews);

你最终得到:

2012-08-02 15:59:30.145 Example[16702:303] (
    "<_NSThemeCloseWidget: 0x100523dc0>", // the close button
    "<_NSThemeWidget: 0x100525ce0>", // the minimize button?
    "<_NSThemeWidget: 0x100524e90>", // the maximize button?
    "<NSView: 0x100512ad0>", // the content view
    "<__NSInspectorBarView: 0x100529d50>", // the inspector view
    "(<NSToolbarView: 0x10054e650>: FD2E0533-AB18-4E7E-905A-AC816CB80A26)" // the toolbar
)

如您所见,AppKit将检查器栏与其他顶级窗口控件置于同一级别。现在这进入了私有 API 的领域,但简单地修补“窗口视图”不应该让任何应用程序被拒绝。


您可以尝试__NSInspectorBarView从此处获取对 的参考。似乎它总是紧跟在内容视图之后的子视图,所以这样的事情可能会起作用:

NSArray *topLevelViews = [self.testTextView.window.contentView superview].subviews;
NSUInteger indexOfContentView = [topLevelViews indexOfObject:self.testTextView.window.contentView];
if (indexOfContentView + 1 < topLevelViews.count) {
    NSView *inspectorBar = [topLevelViews objectAtIndex:indexOfContentView + 1];
    NSLog(@"%@", inspectorBar);
}
NSLog(@"%@", topLevelViews);

如果 Apple 更改顶级视图的顺序,这会立即中断,因此对于生产应用程序可能不是一个好主意。另一个想法是:

NSView *inspectorBarView = nil;
for (NSView *topLevelView in topLevelViews) {
    if ([topLevelView isKindOfClass:NSClassFromString(@"__NSInspectorBarView")]) {
        inspectorBarView = topLevelView;
    }
}
NSLog(@"%@", inspectorBarView);

我不知道使用是否NSClassFromString()会通过 App Store 审查指南,但是,因为它再次依赖于私有 API。


话虽如此,一旦您获得对检查栏视图的引用,事情仍然不能很好地工作。您可以尝试在底部重新定位它:

if (inspectorBarView) {
    NSRect newFrame = inspectorBarView.frame;
    newFrame.origin = NSZeroPoint;
    [inspectorBarView setAutoresizingMask:NSViewMaxYMargin | NSViewMaxXMargin];
    [inspectorBarView setFrame:newFrame];
}

但是你最终会得到一个错误绘制的工具栏,所以需要做更多的工作:

在此处输入图像描述

我的想法是尝试将内容视图的高度向上移动以覆盖灰色的剩余区域(每次调整窗口大小时都必须这样做,也许修补自动调整大小的蒙版可能会更容易)并自定义绘制底部检查器栏的背景。

编辑

哦,您也应该为此提交功能请求。bugreport.apple.com

于 2012-08-02T23:24:20.013 回答
5

这已经晚了四年,但我觉得互联网上的某个人将来可能会从中受益。我花了太长时间试图弄清楚这一点。

正如其他人所指出的,检查栏类似乎是一个私有类(__NSInspectorBarView)。因此,可能不建议修改。

尽管如此!好奇的人必须知道。在本文发布时(2016 年 4 月),检查器栏已插入到窗口的附件栏中。NSWindow从 OS X 10.10 开始,您可以使用被调用的数组属性获取附件视图列表titlebarAccessoryViewControllers[]

这里有一些 Swift 2.0 代码可以做到这一点,假设您事先没有在窗口中插入任何其他附件视图

if window.titlebarAccessoryViewControllers.count > 0 {
        let textViewInspectorBar = self.titlebarAccessoryViewControllers[0].view
        let inspectorBarHeight: CGFloat = textViewInspectorBar!.frame.height // 26.0 pt
    }

值得注意的是,附件视图在全屏模式应用程序中的处理方式不同https ://developer.apple.com/library/mac/documentation/General/Conceptual/MOSXAppProgrammingGuide/FullScreenApp/FullScreenApp.html

我个人不会尝试移动附件视图,因为它们是特殊类型的视图,旨在保留在工具栏中(如果我完全理解我所读的内容)。

NSTitlebarAccessoryViewController 参考: https ://developer.apple.com/library/mac/documentation/AppKit/Reference/NSTitlebarAccessoryViewController_Class/

于 2016-04-03T04:56:14.827 回答
2

又过了 3 年,但我怀疑有些人会觉得这很有用。我的具体问题是让一个窗口完全被 tabView 填满 - 非常适合设置各种用户默认值。这些标签页中只有一个有几个文本视图,我希望检查器栏可见。跳转到那个页面会出现检查栏,并将整个页面向下推,破坏了我精心设计的布局。离开页面并没有再次隐藏它。

显而易见的事情是让检查栏只出现在相关的标签页上。掌握了它(“站在巨人的肩膀上”——感谢巨人 Vervious),在视图层次结构中重新定位它相对容易。您仍然会遇到将内容向下推的空工具栏的空间问题。当检查栏第一次出现时,窗口的视图层次结构发生了根本性的变化,我放弃了尝试用它做任何事情。我的解决方案是增加内容视图的高度。(为什么高度而不是起源我不能说。)

func tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?) {
  if let inspectorBar = window!.titlebarAccessoryViewControllers.first(where:
    {$0.view.className == "__NSInspectorBarView"} )?.view {

    // move content view back to where it should be
    var sz = window!.contentView!.frame.size
    sz.height = window!.frame.size.height - 21
    window!.contentView?.setFrameSize(sz)

    // put the inspector where we want it
    inspectorBar.removeFromSuperview()
    let y = textPage.frame.size.height - inspectorBar.frame.size.height - 10
    inspectorBar.setFrameOrigin(NSPoint(x: 0, y: y))
    textPage.subviews.insert(inspectorBar, at: 0)
  }
}

该代码属于NSTabViewDelegate我使我的窗口控制器符合的代码,记住将 tabView 的委托设置为 xib 中的文件所有者,并在选择新选项卡时调用。textPage是相关 tabViewItem 内的视图。

通过反复试验发现了一些任意常数。该功能只需要运行一次。重复调用是无害的,但您可以设置一个标志以从后续调用中提前返回。

于 2019-05-20T12:15:15.970 回答
0

你不能做任何事情来定位这个东西。显然,@Vervious 指出的损坏是真实的,前提是您没有 NSToolBar。你看,这个inspectorBar 很遗憾是一个主要是私有的并且大部分(公开)无证但很棒的工具。而且它非常适合在具有可见 NSToolBar 的窗口中使用......看图。

将工具栏添加到视图后 将工具栏添加到视图后

仍然有一个工具栏但隐藏了,并且检查栏很酷 (如通过视图菜单或它调用的方法,即 toggleToolBarShown: 并且是 NSResponder 友好消息) 仍然有一个工具栏但被隐藏了,检查栏很酷

所以很明显,不,你不能做太多。它的设计记录很差。它可以作为 NSToolbar 所在位置下的伪附件视图栏(这也是不可调节的)

于 2014-08-27T15:36:22.317 回答