我不确定你是否还在寻找答案。我最近正在从事一个项目,该项目恰好需要您描述的非常相似的功能。
您可以在 NSTextView 的子类中执行以下操作:
你要调用的函数是:showRelativeToRect:ofView:preferredEdge:
rect 将是 NSTextView 内部的一个矩形,使用 NSTextView 坐标系,ofView 是 NSTextView,preferredEdge 是你希望这个 popover 东西挂钩的边缘。
现在,您说您希望在插入符号下显示 PopOver 事物,那么您必须给他一个 Rect,一个 Point 是不够的。NSTextView 有一个名为 selectedRange 的选择器,它为您提供所选文本的范围,您可以使用它来定位您的插入符号。
接下来就是调用firstRectForCharacterRange(该类必须委托NSTextInputClient),这个方法会返回一个NSTextView里面选中文本的屏幕坐标,然后你把它们转换成NSTextView坐标系,你就可以在上面展示NSPopover这个东西了一个正确的位置。这是我这样做的代码。
NSRect rect = [self firstRectForCharacterRange:[self selectedRange]]; //screen coordinates
// Convert the NSAdvancedTextView bounds rect to screen coordinates
NSRect textViewBounds = [self convertRectToBase:[self bounds]];
textViewBounds.origin = [[self window] convertBaseToScreen:textViewBounds.origin];
rect.origin.x -= textViewBounds.origin.x;
rect.origin.y -= textViewBounds.origin.y;
rect.origin.y = textViewBounds.size.height - rect.origin.y - 10; //this 10 is tricky, if without, my control shows a little below the text, which makes it ugly.
NSLog(@"rect %@", NSStringFromRect(rect));
NSLog(@"bounds %@", NSStringFromRect([self bounds]));
if([popover isShown] == false)
[popover showRelativeToRect:rect
ofView:self preferredEdge:NSMaxYEdge];
这就是结果。
我想知道的是,如果有一种方法可以使用系统函数进行转换,虽然我尝试了 convertRect:toView,但是由于这个方法是用委托编写的,所以 NSTextView 的坐标系总是 (0,0) ,这使得这种方法毫无用处。