我已经搜索了如何执行此操作,但找不到任何答案。
我想知道我NSTextfield
是否已经在截断文本(最后...),而无需检查其stringValue
. 我需要这样做才能知道是否应该在我的NSTextfield
(就像一个简单的标签)上设置一个工具提示。
我不想检查文本字段长度stringValue
的原因是因为有些字符比其他字符占用更多空间,所以这不是很准确
谢谢!
4 回答
对于未来的访问者,您可以使用该-[NSCell expansionFrameWithFrame:inView:]
方法来确定是否正在发生截断。从标题:
如果 cellFrame 对于视图中的全部内容来说太小,则允许单元格返回扩展单元格框架。...<snip>...如果框架不是太小,返回一个空矩形,并且不会显示扩展工具提示视图。默认情况下,NSCell 返回 NSZeroRect,而一些子类(例如 NSTextFieldCell)会在需要时返回正确的帧。
简而言之,您可以判断 anNSTextField
是否像这样截断:
NSRect expansionRect = [[self cell] expansionFrameWithFrame: self.frame inView: self];
BOOL truncating = !NSEqualRects(NSZeroRect, expansionRect);
您最好的选择可能是使用 aNSTextView
而不是 a NSTextField
。如果您使用 an ,NSTextView
您可以获得using属性NSTextContainer
的。容器可以告诉您(绘制文本的空间)。NSTextView
textContainer
containerSize
NSString
对象响应方法sizeWithAttributes:
。如果使用给定的属性绘制,您可以使用生成的NSSize
结构来获取文本的宽度。请参阅NSAttributedString Application Kit Additions Reference的“常量”部分来确定哪些属性是相关的。
如果containerSize
宽度小于sizeWithAttributes:
宽度,则文本将被截断。
编辑:抱歉,这仅适用于 no lineFragmentPadding
,但默认lineFragmentPadding
值为非零。要么减去textContainer.lineFragmentPadding
fromcontainerSize.width
或使用NSTextContainer
setLineFragmentPadding:
方法将其设置为0
。
我想你也可以对文本区域的大小做出一些假设,NSTextField
并结合使用该sizeWithAttributes:
NSString
方法,但这并不那么干净。
编辑 2:我意识到我没有解决 OP 对使用省略号截断文本的兴趣。下面的示例代码在NSTextView
. 我还想我不妨扔一些代码,NSTextView
通过NSTextField
把它放在一个NSBox
. 添加大小检查以确定是否应显示工具提示将是使用上面已经提到的信息对以下代码的简单添加。
NSString* string = @"Hello World.";
// get the size the text will take up using the default font
NSSize textBounds = [string sizeWithAttributes:@{}];
// Create a border view that looks more or less like the border used around
// text fields
NSBox* borderView = [[NSBox alloc] initWithFrame:NSMakeRect(10, 10, 60, textBounds.height+4)];
[borderView setBoxType:NSBoxCustom];
[borderView setBorderType:NSBezelBorder];
[borderView setContentViewMargins:NSMakeSize(0, 0)];
[borderView setFillColor:[NSColor whiteColor]];
// Create the text view
NSTextView* textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 60, textBounds.height)];
[textView setTextContainerInset:NSMakeSize(2, 0)];
[textView.textContainer setLineFragmentPadding:0];
[textView setEditable:YES];
// Set the default paragraph style so the text is truncated rather than
// wrapped
NSMutableParagraphStyle* parStyle = [[NSMutableParagraphStyle alloc] init];
[parStyle setLineBreakMode:NSLineBreakByTruncatingTail];
// Do not let text get squashed to fit
[parStyle setTighteningFactorForTruncation:0.0];
[textView setDefaultParagraphStyle:parStyle];
[parStyle release];
// Set text
[textView setString:string];
// add NSTextView to border view
[borderView addSubview:textView];
[textView release];
// add NSBox to view you want text view displayed in
[self addSubview:borderView];
[borderView release];
我认为您可以通过查看文本字段的字段编辑器的框架来做到这一点。您在 controlTextDidBeginEditing 中检查其宽度,然后在 controlTextDidEndEditing 中再次检查。如果后一个值较大,则文本已被截断。以下是在文本字段的委托中实现的(我为 initialWidth 创建了一个 ivar):
- (void)controlTextDidBeginEditing:(NSNotification *)aNotification {
if (! initialWidth)
initialWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width;
}
- (void)controlTextDidEndEditing:(NSNotification *)aNotification {
if (initialWidth) { //Make sure that beginEditing is called first
NSInteger finalWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width;
if (finalWidth - initialWidth > 1) NSLog(@"We have truncation");
NSLog(@"Final: %ld Initial: %ld", finalWidth,initialWidth);
}
}
这似乎在大多数情况下都有效,包括如果您输入一个长字符串,然后删除直到它再次适合。在少数情况下,当我超出文本字段末尾一个字符时,它给了我日志消息,但在编辑结束时我没有得到省略号。
使用 ipmcc 作为基础的 Swift 4 解决方案
它将一一调整大小,直到适合或 fontsize = 3
var size_not_ok = true
var conter = 0
let mininum_font_size = 3 // will resize ultil 3
while size_not_ok || conter < 15 { // will try 15 times maximun
let expansionRect = le_nstextfield.expansionFrame(withFrame: le_nstextfield.frame)
let truncated = !NSEqualRects(NSRect.zero, expansionRect)
if truncated {
if let actual_font_size : CGFloat = le_nstextfield.font?.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? CGFloat {
le_nstextfield.font = NSFont.systemFont(ofSize: actual_font_size - 1)
if actual_font_size < mininum_font_size {
break
}
}
} else {
size_not_ok = false
}
conter = conter + 1
}